CedarProcessImpl.mesa
Copyright Ó 1985, 1986, 1987, 1990, 1991 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) January 19, 1987 7:03:28 pm PST
Michael Plass, September 14, 1990 11:30 am PDT
DIRECTORY
AMEvents USING [Debugged, Debugging],
Atom USING [DottedPairNode, PropList],
CedarProcess USING [ForkableProc, ForkOptions, Priority, Process, ProcessList, ProcessRep, Status],
Loader USING [MakeGlobalFrameResident, MakeProcedureResident],
Process USING [CheckForAbort, Detach, GetCurrent, GetPriority, Priority, SetPriority],
ProcessProps USING [GetPropList, PushPropList];
CedarProcessImpl: CEDAR MONITOR
IMPORTS Process, ProcessProps
EXPORTS CedarProcess = {
ForkableProc: TYPE = CedarProcess.ForkableProc;
ForkOptions: TYPE = CedarProcess.ForkOptions;
Priority: TYPE = CedarProcess.Priority;
ProcessRef: TYPE = CedarProcess.Process;
ProcessList: TYPE = CedarProcess.ProcessList;
Status: TYPE = CedarProcess.Status;
Global vars
busyList: CedarProcess.ProcessList ¬ NIL;
busyCount: INT ¬ 0;
statusChange: CONDITION;
Operations for the current process
SetPriority: PUBLIC PROC [priority: Priority] = {
Sets the priority of the current process to the given priority
Process.SetPriority[LOOPHOLE[priority]];
};
GetPriority: PUBLIC PROC RETURNS [priority: Priority] = {
Gets the priority of the current process
RETURN [LOOPHOLE[Process.GetPriority[]]];
};
DoWithPriority: PUBLIC PROC [priority: Priority, action: PROC] = {
Performs the action using the given priority. After the action completes the priority reverts to the priority before the call.
old: Priority ¬ GetPriority[];
SetPriority[priority];
action[ ! UNWIND => SetPriority[old]];
SetPriority[old];
};
Operations for forked processes
Fork: PUBLIC PROC [action: ForkableProc, data: REF ¬ NIL, options: ForkOptions]
RETURNS [ProcessRef] = TRUSTED {
Forks the action with the given callback data and the given options. Note that the action must NOT be a nested procedure.
new: ProcessRef ¬ NEW[CedarProcess.ProcessRep ¬ [action: action, data: data]];
props: Atom.PropList ¬ ProcessProps.GetPropList[];
Process.Detach[FORK CedarProcessBase[new, props, options]];
WaitForStarted[new];
RETURN [new];
};
GetStatus: PUBLIC ENTRY PROC [process: ProcessRef] RETURNS [Status] = {
Monitored access to process.status.
IF (process ¬ DefaultMe[process]) = NIL THEN RETURN [invalid];
RETURN [process.status];
};
Join: PUBLIC ENTRY PROC [process: ProcessRef, wait: BOOL ¬ TRUE]
RETURNS [status: Status, results: REF] = {
wait = TRUE AND (process.status = debugging OR process.status = busy) =>
wait for (process.status = done OR process.status = aborted)
In all other cases, return the current results and status.
IF process # NIL THEN {
IF wait THEN DO
SELECT process.status FROM
busy, debugging => WAIT statusChange;
ENDCASE => EXIT;
ENDLOOP;
RETURN [process.status, process.results];
};
RETURN [done, NIL];
};
Abort: PUBLIC ENTRY PROC [process: ProcessRef] = {
a monitored call to make process.abortRequested = TRUE
increments process.abortCount
IF process # NIL THEN {
process.abortCount ¬ process.abortCount + 1;
process.abortRequested ¬ TRUE;
};
};
CheckAbort: PUBLIC PROC [process: ProcessRef] = {
a monitored call to make process.abortRequested = TRUE
raises ERROR ABORTED if process.abortRequested was TRUE when called
Process.CheckForAbort[];
CheckAbortEntry[process];
};
Operations for all busy forked processes
GetBusyList: PUBLIC ENTRY PROC RETURNS [head: ProcessList ¬ NIL] = {
Returns a copy of the current busy list of processes.
FOR each: ProcessList ¬ busyList, each.rest WHILE each # NIL DO
SELECT each.first.status FROM
busy, debugging => head ¬ CONS[each.first, head];
ENDCASE;
ENDLOOP;
};
GetBusyCount: PUBLIC ENTRY PROC RETURNS [INT] = {
Returns the number of processes forked through this interface that currently have status = busy or status = debugging.
RETURN [busyCount];
};
Utilities
CheckAbortEntry: ENTRY PROC [process: ProcessRef] = {
IF (process ¬ DefaultMe[process]) # NIL AND process.abortRequested THEN {
process.abortRequested ¬ FALSE;
RETURN WITH ERROR ABORTED;
};
};
DefaultMe: INTERNAL PROC [process: ProcessRef] RETURNS [ProcessRef] = TRUSTED {
IF process = NIL THEN {
me: PROCESS ¬ LOOPHOLE[Process.GetCurrent[]];
FOR each: ProcessList ¬ busyList, each.rest WHILE each # NIL DO
process ¬ each.first;
IF process.process = me THEN RETURN [process];
ENDLOOP;
RETURN [NIL];
};
RETURN [process];
};
WaitForStarted: ENTRY PROC [process: ProcessRef] = {
WHILE process.process = NIL DO WAIT statusChange; ENDLOOP;
};
AdjustDebugCount: ENTRY PROC [process: ProcessRef, delta: INT] = {
process.debugCount ¬ process.debugCount + delta;
};
CedarProcessBase: PROC [new: ProcessRef, props: Atom.PropList, options: ForkOptions] = {
innerProcessBase: PROC = TRUSTED {
me: PROCESS ¬ LOOPHOLE[Process.GetCurrent[]];
AddToBusyList[new];
new.results ¬ new.action[new.data
!
AMEvents.Debugging => AdjustDebugCount[new, 1];
AMEvents.Debugged => AdjustDebugCount[new, -1];
ABORTED => GO TO abort;
];
RemFromBusyList[new, done];
EXITS abort => RemFromBusyList[new, aborted];
};
IF options.usePriority THEN Process.SetPriority[LOOPHOLE[options.priority]];
IF NOT options.inheritProperties THEN props ¬ NIL;
props ¬ CONS[NEW[Atom.DottedPairNode ¬ [$CedarProcess, new]], props];
ProcessProps.PushPropList[props, innerProcessBase];
};
AddToBusyList: ENTRY PROC [process: ProcessRef] = TRUSTED {
busyList ¬ CONS[process, busyList];
process.process ¬ LOOPHOLE[Process.GetCurrent[]];
busyCount ¬ busyCount + 1;
BROADCAST statusChange;
};
RemFromBusyList: ENTRY PROC [process: ProcessRef, status: Status] = {
SELECT TRUE FROM
busyList = NIL => {};
busyList.first = process => {
busyCount ¬ busyCount - 1;
busyList ¬ busyList.rest;
};
ENDCASE => {
lag: ProcessList ¬ busyList;
DO
next: ProcessList ¬ lag.rest;
IF next = NIL THEN EXIT;
IF next.first.process = process.process THEN {
busyCount ¬ busyCount - 1;
lag.rest ¬ next.rest;
EXIT;
};
lag ¬ next;
ENDLOOP;
};
process.status ¬ status;
BROADCAST statusChange;
};
Temporary
Loader.MakeGlobalFrameResident[SetPriority];
Loader.MakeProcedureResident[SetPriority];
Loader.MakeProcedureResident[GetPriority];
}.
CHANGE LOG
Russ Atkinson (RRA) August 19, 1985 2:35:11 pm PDT
in CedarProcessBase
old: IF options.inheritProperties THEN props ← NIL;
new: IF NOT options.inheritProperties THEN props ← NIL;
Russ Atkinson (RRA) August 19, 1985 10:12:26 pm PDT
in CedarProcessBase -
old: AMEvents.Debugging => AdjustDebugCount[new, -1];
new: AMEvents.Debugged => AdjustDebugCount[new, -1];
Michael Plass, September 14, 1990
Removed references to AMEvents and Loader.