EditNotifyImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
written by Bill Paxton, March 1981
last edit by Bill Paxton, October 18, 1982 10:42 am
Doug Wyatt, March 3, 1985 4:39:51 pm PST
Michael Plass, March 29, 1985 2:31:39 pm PST
DIRECTORY
EditNotify;
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: ChangeType;
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] =
{ RETURN [IF time=before THEN beforeProcs[p] ELSE afterProcs[p]] };
END.