FinalizeOpsImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 17, 1992 1:45:01 pm PDT
Christian Jacobi, July 22, 1992 10:50 am PDT
DIRECTORY
Finalize,
FinalizeOps,
Process;
FinalizeOpsImpl: CEDAR MONITOR
IMPORTS Finalize, Process
EXPORTS FinalizeOps
~ BEGIN
Handle: TYPE = FinalizeOps.Handle;
FinalizeProc: TYPE = FinalizeOps.FinalizeProc;
CallQueue: TYPE = REF CallQueueRep;
CallQueueRep: PUBLIC TYPE = MONITORED RECORD [
finalize: FinalizeProc,
priority: Process.Priority,
active: BOOL ¬ FALSE,
front: LIST OF Handle ¬ NIL,
tail: LIST OF Handle ¬ NIL
];
fq: Finalize.FinalizationQueue ~ Finalize.NewFQ[];
IsCallQueue: PUBLIC PROC [x: REF] RETURNS [BOOL] = {
RETURN [ISTYPE[x, CallQueue]]
};
NarrowCallQueue: PUBLIC PROC [x: REF] RETURNS [CallQueue] = {
RETURN [NARROW[x, CallQueue]]
};
IsFinalizeOpsHandle: PUBLIC PROC [handle: Finalize.Handle] RETURNS [BOOL] = {
WITH Finalize.GetClientData[handle] SELECT FROM
cq: CallQueue => RETURN [TRUE];
ENDCASE => RETURN [FALSE];
};
EnableFinalization: PUBLIC PROC [object: REF, callQueue: FinalizeOps.CallQueue] RETURNS [handle: Handle] = {
handle ¬ Finalize.EnableFinalization[object, fq, callQueue];
};
ReenableFinalization: PUBLIC PROC [handle: Handle] RETURNS [oldState: Finalize.FinalizationState] = {
WITH Finalize.GetClientData[handle] SELECT FROM
cq: CallQueue => oldState ¬ Finalize.ReenableFinalization[handle, fq];
ENDCASE => ERROR;
};
CreateCallQueue: PUBLIC PROC [finalize: FinalizeProc, priority: Process.Priority ¬ Process.priorityForeground] RETURNS [cq: CallQueue] = {
cq ¬ NEW[CallQueueRep ¬ [finalize: finalize, priority: priority]];
};
HandleToObject: PUBLIC PROC [handle: Handle] RETURNS [object: REF] = {
RETURN [Finalize.HandleToObject[handle]]
};
freeList: LIST OF Handle ¬ NIL;
DisposeList: INTERNAL PROC [l: LIST OF Handle] = INLINE {
l.first ¬ NIL;
l.rest ¬ freeList;
freeList ¬ l
};
NewList: INTERNAL PROC [h: Handle] RETURNS [l: LIST OF Handle] = INLINE {
l ¬ freeList;
IF l=NIL THEN l ¬ LIST[h] ELSE {freeList ¬ l.rest; l.first ¬ h; l.rest ¬ NIL}
};
Forward: ENTRY PROC [cq: CallQueue, h: Handle] RETURNS [mustFork: BOOL ¬ FALSE] = {
--Assert h#NIL
list: LIST OF Handle ¬ NewList[h];
IF cq.front=NIL
THEN cq.front ¬ list
ELSE cq.tail.rest ¬ list;
cq.tail ¬ list;
IF ~cq.active THEN cq.active ¬ mustFork ¬ TRUE;
};
Fetch: ENTRY PROC [cq: CallQueue] RETURNS [h: Handle ¬ NIL] = {
--If h=NIL the process is terminated
l: LIST OF Handle ¬ cq.front;
IF l#NIL
THEN {h ¬ l.first; cq.front ¬ l.rest; DisposeList[l]}
ELSE cq.active ¬ FALSE;
};
CallQueueProcess: PROC [cq: CallQueue] = {
Process.SetPriority[cq.priority];
DO
ENABLE ABORTED => LOOP;
DO
h: Handle ¬ Fetch[cq];
IF h=NIL THEN RETURN;
cq.finalize[h, Finalize.HandleToObject[h]];
ENDLOOP;
ENDLOOP;
};
MainQueueProcess: PROC [] = {
Process.SetPriority[Process.priorityForeground];
DO
handle: Handle ¬ Finalize.FQNextNoAbort[fq];
IF handle#NIL THEN {
WITH Finalize.GetClientData[handle] SELECT FROM
cq: CallQueue => {
IF Forward[cq, handle].mustFork THEN TRUSTED {
Process.Detach[FORK CallQueueProcess[cq]];
};
};
ENDCASE => {};
handle ¬ NIL;
};
ENDLOOP;
};
TRUSTED {
Process.Detach[FORK MainQueueProcess[]];
};
END.