<<>> <> <> <> <> <> <> <> 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] = { <> 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] = { <> 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.