CedarProcessImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) August 19, 1985 10:14:50 pm 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 AMEvents, Loader, 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;
busyList: CedarProcess.ProcessList ← NIL;
busyCount: INT ← 0;
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];
}.
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];