CDEventsImpl.mesa
Copyright © 1983 by Xerox Corporation. All rights reserved.
by Christian Jacobi September 16, 1983 2:11 pm
last edited by Christian Jacobi March 21, 1986 2:22:52 pm PST
DIRECTORY
CDEvents,
CD,
RefTab;
CDEventsImpl:
CEDAR
MONITOR
IMPORTS CD, RefTab
EXPORTS CDEvents =
BEGIN
EventProc: TYPE = CDEvents.EventProc;
EventRegistration: TYPE = REF EventRegistrationRep;
EventRegistrationRep:
PUBLIC
TYPE =
RECORD [
event: REF,
eventProcs: EventProcs←NIL,
reverse: BOOL←FALSE,
continueOnAbort: BOOL←TRUE
];
EventProcs: TYPE = LIST OF RECORD [proc: EventProc, filter: CD.Technology];
eventNameTable: RefTab.Ref ~ RefTab.Create[];
RegisterEventType:
PUBLIC
PROC [event:
REF, reverse:
BOOL←
FALSE, continueOnAbort:
BOOL←
TRUE]
RETURNS [EventRegistration] = {
--returns EventRegistration=NIL if eventName is already used.
--the EventRegistration is the key to call ProcessEvent
--if ATOM are used for eventName, include them manual in the list
--on file [ivy]<jacobi>ChipNDale>CDEvents-registration.txt
evr: EventRegistration ← NEW[EventRegistrationRep ← [event: event, reverse: reverse, continueOnAbort: continueOnAbort]];
IF ~RefTab.Insert[eventNameTable, event, evr] THEN ERROR CD.Error[doubleRegistration];
RETURN [evr]
};
GetReg:
PROC [event:
REF]
RETURNS [EventRegistration] = {
WITH event
SELECT
FROM
evr: EventRegistration => RETURN [evr];
ENDCASE => {
WITH RefTab.Fetch[eventNameTable, event].val
SELECT
FROM
evr: EventRegistration => RETURN [evr];
ENDCASE => ERROR CD.Error[missingRegistration];
}
};
RegisterEventProc:
PUBLIC
ENTRY PROC [event:
REF, proc: EventProc, filter:
CD.Technology←
NIL] = {
--registers a procedure which is called each time a specific event occurs
--the procedure might stop certain events with the dont result
--if filter#NIL, proc is only called if event occurs on design of technology=filter
--event must have been previously registered with RegisterEventType
ev: EventRegistration ← GetReg[event];
IF ev.eventProcs=NIL THEN ev.eventProcs←LIST[[proc, filter]]
ELSE IF ev.reverse THEN ev.eventProcs ← CONS[[proc, filter], ev.eventProcs]
ELSE
FOR l: EventProcs ← ev.eventProcs, l.rest
DO
IF l.rest=NIL THEN {l.rest←LIST[[proc, filter]]; RETURN}
ENDLOOP
};
ProcessEvent:
PUBLIC
PROC [eventRegistration: EventRegistration, design:
CD.Design, x:
REF←
NIL, listenToDont:
BOOL←
FALSE]
RETURNS [dont:
BOOL←
FALSE] = {
IF eventRegistration#
NIL
THEN
FOR l: EventProcs ← eventRegistration.eventProcs, l.rest
WHILE l#
NIL
DO
IF l.first.filter#
NIL
AND
(design=NIL OR l.first.filter#design.technology) THEN LOOP;
dont ← l.first.proc[eventRegistration.event, design, x
! ABORTED => IF eventRegistration.continueOnAbort THEN CONTINUE].dont;
IF dont AND listenToDont THEN RETURN;
ENDLOOP
};
END.