EditNotifyImpl.mesa; written by Bill Paxton, March 1981
edited by McGregor, February 8, 1983 11:33 am
edited by Bill Paxton, June 1, 1983 11:34 am
DIRECTORY
EditNotify,
TiogaNode,
TiogaNodeOps;
EditNotifyImpl: CEDAR MONITOR EXPORTS EditNotify = BEGIN OPEN EditNotify;
NotifyList: TYPE = REF NotifyListBody;
NotifyListBody: TYPE = RECORD [
next: NotifyList,
action: EditNotifyProc,
changeSet: ChangeSet ];
NotifyArray: TYPE = ARRAY Priority OF NotifyList;
beforeProcs: NotifyArray;
afterProcs: NotifyArray;
**** Notification Operations ****
unlocked: CONDITION;
lockCount: INTEGER ← 0;
Lock: ENTRY PROC = { lockCount ← lockCount+1 };
Unlock: ENTRY PROC = {
IF (lockCount ← lockCount-1) <= 0 THEN { lockCount ← 0; BROADCAST unlocked }};
AddNotifyProc: PUBLIC ENTRY PROC [
proc: EditNotifyProc,
time: When ← after,
priority: Priority ← normal,
changeSet: ChangeSet ← defaultChangeSet] = {
ENABLE UNWIND => NULL;
WHILE lockCount > 0 DO WAIT unlocked; ENDLOOP;
RemoveNotify[proc, time];
IF time=before THEN
beforeProcs[priority] ← NEW[NotifyListBody ← [beforeProcs[priority], proc, changeSet]]
ELSE afterProcs[priority] ← NEW[NotifyListBody ← [afterProcs[priority], proc, changeSet]]};
RemoveNotifyProc: PUBLIC ENTRY PROC
[proc: EditNotifyProc, time: When ← after] = {
remove proc from list of notification procedures
ENABLE UNWIND => NULL;
WHILE lockCount > 0 DO WAIT unlocked; ENDLOOP;
RemoveNotify[proc, time] };
RemoveNotify: PROC
[proc: EditNotifyProc, time: When ← after] = {
FOR p:Priority IN Priority DO
prev: NotifyList ← NIL;
list: NotifyList ← IF time=before THEN beforeProcs[p]
ELSE afterProcs[p];
IF list=NIL THEN LOOP;
UNTIL list=NIL DO
IF list.action = proc THEN EXIT;
prev ← list; list ← list.next;
REPEAT FINISHED => LOOP; -- proc not found on this list
ENDLOOP;
IF prev#NIL THEN prev.next ← list.next
ELSE IF time=before THEN beforeProcs[p] ← list.next
ELSE afterProcs[p] ← list.next;
ENDLOOP };
Notify: PUBLIC PROC [change: REF READONLY Change, time: When] = {
call notification procedures
ENABLE UNWIND => Unlock[];
kind: OfChange;
IF change=NIL THEN RETURN;
kind ← change.kind;
Lock[];
FOR p:Priority IN Priority DO
FOR lst:NotifyList ← GetList[p,time], lst.next UNTIL lst=NIL DO
IF lst.changeSet[kind] THEN lst.action[change];
ENDLOOP;
ENDLOOP;
Unlock[] };
GetList: PROC [p:Priority, time:When] RETURNS [NotifyList] = INLINE
{ RETURN [IF time=before THEN beforeProcs[p] ELSE afterProcs[p]] };
END.