[Indigo]<Rosemary>®>Rosemary.DF=>RoseEventsImpl.Mesa
Last Edited by: Spreitzer, October 17, 1985 10:03:56 pm PDT
DIRECTORY Asserting, Atom, IO, List, RoseEvents, RoseSimTypes, RoseWireTypes;
RoseEventsImpl: CEDAR PROGRAM
IMPORTS Asserting, Atom, List
EXPORTS RoseEvents =
BEGIN OPEN RoseWireTypes, RoseSimTypes;
all: PUBLIC REF ANYNEW [ROPE ← "All watcheds"];
watchersKey: ATOM ← Atom.MakeAtom["Spreitzer January 6, 1984 8:07 pm"];
ForWatchers: PROC [event: ATOM, watched: REF ANY, do: PROC [WatcherList] RETURNS [WatcherList], replace: BOOL] = {
wll: List.AList;
wl: WatcherList;
IF watched # NIL THEN WITH watched SELECT FROM
roseWire: RoseWire => {
SELECT roseWire.group FROM
aboveLeaf => {
FOR i: NAT IN [0 .. roseWire.subWires.length) DO
ForWatchers[event, roseWire.subWires[i], do, replace];
ENDLOOP;
};
leaf => {
SELECT event FROM
$ChangeEarly => roseWire.watchers[high] ← do[roseWire.watchers[high]];
$ChangeLate => roseWire.watchers[ordinary] ← do[roseWire.watchers[ordinary]];
ENDCASE => BEGIN
wl ← NARROW[Asserting.FnVal[fn: event, from: roseWire.other]];
wl ← do[wl];
IF replace THEN roseWire.other ← Asserting.AssertFn1[fn: event, val: wl, inAdditionTo: roseWire.other];
END;
};
belowLeaf => {
IF roseWire.parent = NIL THEN ERROR;
ForWatchers[event, roseWire.parent, do, replace];
};
ENDCASE => ERROR;
RETURN};
rci: RoseCellInstance => {
SELECT event FROM
$Schedule => {rci.schedWatchers ← do[rci.schedWatchers]};
$Eval => {rci.evalWatchers ← do[rci.evalWatchers]};
ENDCASE => BEGIN
wl ← NARROW[Asserting.FnVal[fn: event, from: rci.other]];
wl ← do[wl];
IF replace THEN rci.other ← Asserting.AssertFn1[fn: event, val: wl, inAdditionTo: rci.other];
END;
RETURN};
ENDCASE;
wll ← NARROW[Atom.GetProp[atom: event, prop: watchersKey]];
wl ← NARROW[List.Assoc[key: watched, aList: wll]];
wl ← do[wl];
IF replace THEN {
wll ← List.PutAssoc[key: watched, val: wl, aList: wll];
Atom.PutProp[atom: event, prop: watchersKey, val: wll];
};
};
AddWatcher: PUBLIC PROC [event: ATOM, watcher: Watcher, watched: REF ANYNIL] =
BEGIN
Addit: PROC [ohne: WatcherList] RETURNS [mit: WatcherList] =
{mit ← CONS[watcher, ohne]};
ForWatchers[event, watched, Addit, TRUE];
END;
RemoveWatcher: PUBLIC PROC [event: ATOM, watcher: Watcher, watched: REF ANYNIL] =
BEGIN
RemoveIt: PROC [watchers: WatcherList] RETURNS [ohne: WatcherList] = {
cur, prev: WatcherList ← NIL;
ohne ← watchers;
FOR cur ← watchers, cur.rest WHILE cur # NIL DO
IF cur.first = watcher THEN {
IF prev = NIL THEN ohne ← cur.rest ELSE prev.rest ← cur.rest;
RETURN
};
prev ← cur;
ENDLOOP;
};
ForWatchers[event, watched, RemoveIt, TRUE];
END;
Notify: PUBLIC PROC [event: ATOM, watched: REF ANYNIL, arg: REF ANYNIL] =
BEGIN
handleAborted: BOOL = TRUE;
abort: BOOLEANFALSE;
abortedWatchers: WatcherList ← NIL;
NotifyEm: PROC [wl: WatcherList] RETURNS [same: WatcherList] = {
same ← wl;
FOR wl ← wl, wl.rest WHILE wl # NIL DO
wl.first.Notify[
event: event,
watched: watched,
watcherData: wl.first.watcherData,
arg: arg
!ABORTED => IF handleAborted THEN {
abort ← TRUE;
abortedWatchers ← CONS[wl.first, abortedWatchers];
CONTINUE}];
ENDLOOP;
};
IF watched = all THEN ERROR;
ForWatchers[event, watched, NotifyEm, FALSE];
ForWatchers[event, all, NotifyEm, FALSE];
IF abort THEN ERROR ABORTED;
END;
END.