ResourceImpl.mesa
Last Modified On April 11, 1983 4:57 pm By Paul Rovner
Last Modified On April 18, 1983 5:58 pm By Russ Atkinson
DIRECTORY
Process USING [InitializeCondition, SecondsToTicks],
Resource USING [AbortProc],
Rope USING [ROPE];
ResourceImpl:
CEDAR
MONITOR
IMPORTS Process
EXPORTS Resource
= BEGIN OPEN Resource;
This interface is intended to provide more flexibility than MONITORs for managing resources that support only one client at a time (e.g. Compiler, Binder, DFFile software). "resource" is typically an ATOM; the implementations of Acquire and Release use =. Acquire will return success = FALSE either if waitForIt = FALSE and the resource is in use (i.e. previously "Acquire'd" but not yet released), or if waitForIt = TRUE and abortProc # NIL and a call on abortProc returned TRUE. If Acquire returns success = FALSE then ownedBy will identify the current owner.
ownees: LIST OF Ownee ← NIL;
Ownee: TYPE = RECORD[resource: REF ANY, owner: Rope.ROPE];
released: CONDITION;
Acquire:
PUBLIC
ENTRY
PROC
[resource: REF ANY,
waitForIt: BOOL ← FALSE,
owner: Rope.ROPE ← NIL,
abortProc: AbortProc ←
NIL,
if non-NIL, abortProc[abortProcData] is called occasionally while Acquire is waiting
abortProcData: REF ANY ← NIL
]
RETURNS[success: BOOL, ownedBy: Rope.ROPE] = {
ENABLE UNWIND => NULL;
DO {
FOR l:
LIST
OF Ownee ← ownees, l.rest
UNTIL l =
NIL DO
IF l.first.resource = resource
THEN
IF waitForIt
THEN {
WAIT released;
IF abortProc #
NIL
AND abortProc[abortProcData]
THEN RETURN[FALSE, l.first.owner];
GOTO tryAgain}
ELSE RETURN[FALSE, l.first.owner];
ENDLOOP;
ownees ← CONS[[resource: resource, owner: owner], ownees];
RETURN[TRUE, owner];
EXITS tryAgain => LOOP;
} ENDLOOP;
};
Release:
PUBLIC
ENTRY
PROC[resource:
REF
ANY]
RETURNS[success:
BOOL] = {
ENABLE UNWIND => NULL;
prev: LIST OF Ownee ← NIL;
FOR l:
LIST
OF Ownee ← ownees, l.rest
UNTIL l =
NIL DO
IF l.first.resource = resource
THEN {
IF prev = NIL THEN ownees ← l.rest ELSE prev.rest ← l.rest;
BROADCAST released;
RETURN[TRUE]}
ELSE prev ← l;
ENDLOOP;
RETURN[FALSE];
};
IsAvailable:
PUBLIC
ENTRY
PROC[resource:
REF
ANY]
RETURNS[yes: BOOL, owner: Rope.ROPE] = {
BEWARE of races; caveat emptor
ENABLE UNWIND => NULL;
FOR l:
LIST
OF Ownee ← ownees, l.rest
UNTIL l =
NIL DO
IF l.first.resource = resource THEN RETURN[FALSE, l.first.owner];
ENDLOOP;
RETURN[TRUE, NIL];
};
START HERE
TRUSTED{Process.InitializeCondition[@released, Process.SecondsToTicks[1]]};
END.