<<>> <> <> <> <> <<>> <> <<>> <> DIRECTORY MBQueue, RefTab, Rope USING [ROPE], WalnutRegistry, WalnutRegistryInternal, WalnutRegistryPrivate; WalnutRegistryImpl: CEDAR MONITOR IMPORTS RefTab, WalnutRegistryInternal EXPORTS WalnutRegistry, WalnutRegistryPrivate = BEGIN RegistrationEntry: TYPE = REF RegistrationRecord; RegistrationRecord: TYPE = RECORD[queue: MBQueue.Queue, eventProc: EventProcEntry ¬ NIL, msgProc: MsgProcEntry ¬ NIL, msgGroupProc: MsgGroupEntry ¬ NIL, moveProc: MoveProcEntry ¬ NIL, msgSetProc: MsgSetProcEntry ¬ NIL]; EventProcEntry: TYPE = REF EventProcRecord; EventProcRecord: TYPE = RECORD[clientData: REF ANY, proc: WalnutRegistry.EventProc, parent: RegistrationEntry, next, prev: EventProcEntry]; MsgProcEntry: TYPE = REF MsgProcRecord; MsgProcRecord: TYPE = RECORD[clientData: REF ANY, proc: WalnutRegistry.MsgProc, parent: RegistrationEntry, next, prev: MsgProcEntry]; MoveProcEntry: TYPE = REF MoveProcRecord; MoveProcRecord: TYPE = RECORD[clientData: REF ANY, proc: WalnutRegistry.MoveProc, parent: RegistrationEntry, next, prev: MoveProcEntry]; MsgGroupEntry: TYPE = REF MsgGroupRecord; MsgGroupRecord: TYPE = RECORD[clientData: REF ANY, proc: WalnutRegistry.MsgGroupProc, parent: RegistrationEntry, next, prev: MsgGroupEntry]; MsgSetProcEntry: TYPE = REF MsgSetProcRecord; MsgSetProcRecord: TYPE = RECORD[clientData: REF ANY, proc: WalnutRegistry.MsgSetProc, parent: RegistrationEntry, next, prev: MsgSetProcEntry]; nextRegistration: CARDINAL ¬ 0; registrationTable: RefTab.Ref = RefTab.Create[]; <> <> eventProcHead: EventProcEntry; msgProcHead: MsgProcEntry; moveProcHead: MoveProcEntry; msgSetProcHead: MsgSetProcEntry; msgGroupHead: MsgGroupEntry; <> stateIs: WalnutRegistry.Event ¬ unknown; CurrentWalnutState: PUBLIC ENTRY PROC RETURNS[walnutState: WalnutRegistry.WalnutState] = { SELECT stateIs FROM unknown => RETURN[unknown]; initializing => RETURN[initializing]; stopped => RETURN[stopped]; ENDCASE => RETURN[active]; }; Register: PUBLIC ENTRY PROC [procSet: WalnutRegistry.ProcSet, queue: MBQueue.Queue] RETURNS[registration: WalnutRegistry.Registration] = { newEntry: RegistrationEntry = NEW[RegistrationRecord ¬ [queue: queue]]; registration ¬ NEW[CARDINAL ¬ nextRegistration]; nextRegistration ¬ nextRegistration+1; [] ¬ RefTab.Store[registrationTable, registration, newEntry]; <> IF procSet.eventProc # NIL THEN { newEntry.eventProc ¬ NEW[EventProcRecord ¬ [clientData: procSet.eventProcData, proc: procSet.eventProc, parent: newEntry]]; newEntry.eventProc.next ¬ eventProcHead; newEntry.eventProc.prev ¬ eventProcHead.prev; eventProcHead.prev.next ¬ newEntry.eventProc; eventProcHead.prev ¬ newEntry.eventProc; IF stateIs # unknown THEN WalnutRegistryInternal.QueueEvent[ stateIs, queue, procSet.eventProc, procSet.eventProcData]; }; IF procSet.msgProc # NIL THEN { newEntry.msgProc ¬ NEW[MsgProcRecord ¬ [clientData: procSet.msgProcData, proc: procSet.msgProc, parent: newEntry]]; newEntry.msgProc.next ¬ msgProcHead; newEntry.msgProc.prev ¬ msgProcHead.prev; msgProcHead.prev.next ¬ newEntry.msgProc; msgProcHead.prev ¬ newEntry.msgProc }; IF procSet.moveProc # NIL THEN { newEntry.moveProc ¬ NEW[MoveProcRecord ¬ [clientData: procSet.moveProcData, proc: procSet.moveProc, parent: newEntry]]; newEntry.moveProc.next ¬ moveProcHead; newEntry.moveProc.prev ¬ moveProcHead.prev; moveProcHead.prev.next ¬ newEntry.moveProc; moveProcHead.prev ¬ newEntry.moveProc }; IF procSet.msgGroupProc # NIL THEN { newEntry.msgGroupProc ¬ NEW[MsgGroupRecord ¬ [clientData: procSet.msgGroupData, proc: procSet.msgGroupProc, parent: newEntry]]; newEntry.msgGroupProc.next ¬ msgGroupHead; newEntry.msgGroupProc.prev ¬ msgGroupHead.prev; msgGroupHead.prev.next ¬ newEntry.msgGroupProc; msgGroupHead.prev ¬ newEntry.msgGroupProc }; IF procSet.msgSetProc # NIL THEN { newEntry.msgSetProc ¬ NEW[MsgSetProcRecord ¬ [clientData: procSet.msgSetData, proc: procSet.msgSetProc, parent: newEntry]]; newEntry.msgSetProc.next ¬ msgSetProcHead; newEntry.msgSetProc.prev ¬ msgSetProcHead.prev; msgSetProcHead.prev.next ¬ newEntry.msgSetProc; msgSetProcHead.prev ¬ newEntry.msgSetProc }; }; InvalidRegistration: PUBLIC ERROR = CODE; UnRegister: PUBLIC ENTRY PROC [registration: WalnutRegistry.Registration] = { entry: RegistrationEntry = NARROW[RefTab.Fetch[registrationTable, registration].val]; IF entry = NIL THEN ERROR InvalidRegistration; IF entry.eventProc # NIL THEN { entry.eventProc.prev.next ¬ entry.eventProc.next; entry.eventProc.next.prev ¬ entry.eventProc.prev; entry.eventProc.parent ¬ NIL }; IF entry.msgProc # NIL THEN { entry.msgProc.prev.next ¬ entry.msgProc.next; entry.msgProc.next.prev ¬ entry.msgProc.prev; entry.msgProc.parent ¬ NIL }; IF entry.moveProc # NIL THEN { entry.moveProc.prev.next ¬ entry.moveProc.next; entry.moveProc.next.prev ¬ entry.moveProc.prev; entry.moveProc.parent ¬ NIL }; IF entry.msgGroupProc # NIL THEN { entry.msgGroupProc.prev.next ¬ entry.msgGroupProc.next; entry.msgGroupProc.next.prev ¬ entry.msgGroupProc.prev; entry.msgGroupProc.parent ¬ NIL }; IF entry.msgSetProc # NIL THEN { entry.msgSetProc.prev.next ¬ entry.msgSetProc.next; entry.msgSetProc.next.prev ¬ entry.msgSetProc.prev; entry.msgSetProc.parent ¬ NIL }; [] ¬ RefTab.Delete[registrationTable, registration] }; GetProcs: PUBLIC ENTRY PROC[registration: WalnutRegistry.Registration] RETURNS[procSet: WalnutRegistry.ProcSet, queue: MBQueue.Queue] = { entry: RegistrationEntry = NARROW[RefTab.Fetch[registrationTable, registration].val]; IF entry = NIL THEN ERROR InvalidRegistration; queue ¬ entry.queue; IF entry.eventProc # NIL THEN { procSet.eventProc ¬ entry.eventProc.proc; procSet.eventProcData ¬ entry.eventProc.clientData }; IF entry.msgProc # NIL THEN { procSet.msgProc ¬ entry.msgProc.proc; procSet.msgProcData ¬ entry.msgProc.clientData}; IF entry.moveProc # NIL THEN { procSet.moveProc ¬ entry.moveProc.proc; procSet.moveProcData ¬ entry.moveProc.clientData}; IF entry.msgGroupProc # NIL THEN { procSet.msgGroupProc ¬ entry.msgGroupProc.proc; procSet.msgGroupData ¬ entry.msgGroupProc.clientData}; IF entry.msgSetProc # NIL THEN { procSet.msgSetProc ¬ entry.msgSetProc.proc; procSet.msgSetData ¬ entry.msgSetProc.clientData} }; CheckForMsgGroupRegistration: PUBLIC ENTRY PROC RETURNS[yes: BOOL] = { RETURN[msgGroupHead.next.proc # NIL] }; NotifyForEvent: PUBLIC ENTRY PROC[event: WalnutRegistry.Event] = TRUSTED { stateIs ¬ IF event = mailRead THEN started ELSE event; FOR e: EventProcEntry ¬ eventProcHead.next, e.next UNTIL e.proc = NIL DO WalnutRegistryInternal.QueueEvent[event, e.parent.queue, e.proc, e.clientData]; ENDLOOP }; NotifyForMsgEvent: PUBLIC ENTRY PROC[msgEvent: WalnutRegistry.MsgEvent, msg: Rope.ROPE] = TRUSTED { FOR e: MsgProcEntry ¬ msgProcHead.next, e.next UNTIL e.proc = NIL DO WalnutRegistryInternal.QueueMsgEvent[msgEvent, msg, e.parent.queue, e.proc, e.clientData]; ENDLOOP}; NotifyForMove: PUBLIC ENTRY PROC[msg: Rope.ROPE, to, from: Rope.ROPE] = TRUSTED { FOR e: MoveProcEntry ¬ moveProcHead.next, e.next UNTIL e.proc = NIL DO WalnutRegistryInternal.QueueMoveEvent[msg, to, from, e.parent.queue, e.proc, e.clientData]; ENDLOOP}; NotifyForMsgGroup: PUBLIC ENTRY PROC[event: WalnutRegistry.MsgGroupEvent, group: WalnutRegistry.MsgGroup] = TRUSTED { msgGroupCopy: REF WalnutRegistry.MsgGroup = NEW[WalnutRegistry.MsgGroup]; msgGroupCopy­ ¬ group; FOR e: MsgGroupEntry ¬ msgGroupHead.next, e.next UNTIL e.proc = NIL DO WalnutRegistryInternal.QueueMsgGroupEvent[event, msgGroupCopy, e.parent.queue, e.proc, e.clientData]; ENDLOOP}; NotifyForMsgSetEvent: PUBLIC ENTRY PROC[msgSetEvent: WalnutRegistry.MsgSetEvent, msgSet: Rope.ROPE] = TRUSTED { FOR e: MsgSetProcEntry ¬ msgSetProcHead.next, e.next UNTIL e.proc = NIL DO WalnutRegistryInternal.QueueMsgSetEvent[msgSetEvent, msgSet, e.parent.queue, e.proc, e.clientData]; ENDLOOP}; <> eventProcHead ¬ NEW[EventProcRecord ¬ [clientData: NIL, proc: NIL]]; eventProcHead.prev ¬ eventProcHead.next ¬ eventProcHead; msgProcHead ¬ NEW[MsgProcRecord ¬ [clientData: NIL, proc: NIL]]; msgProcHead.prev ¬ msgProcHead.next ¬ msgProcHead; moveProcHead ¬ NEW[MoveProcRecord ¬ [clientData: NIL, proc: NIL]]; moveProcHead.prev ¬ moveProcHead.next ¬ moveProcHead; msgGroupHead ¬ NEW[MsgGroupRecord ¬ [clientData: NIL, proc: NIL]]; msgGroupHead.prev ¬ msgGroupHead.next ¬ msgGroupHead; msgSetProcHead ¬ NEW[MsgSetProcRecord ¬ [clientData: NIL, proc: NIL]]; msgSetProcHead.prev ¬ msgSetProcHead.next ¬ msgSetProcHead; END.