EditNotifyImpl.mesa
Copyright Ó 1985, 1986, 1991 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
Christian Jacobi, May 2, 1989 6:06:30 pm PDT
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] = INLINE {
RETURN [IF time=before THEN beforeProcs[p] ELSE afterProcs[p]] };
END.