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
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;
GetList:
PROC [p: Priority, time: When]
RETURNS [NotifyList] =
INLINE {
RETURN [IF time=before THEN beforeProcs[p] ELSE afterProcs[p]] };
END.