<> <> <> <> <<>> <> <<>> <> 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; <> stateIsKnown: BOOL _ FALSE; stateIs: WalnutRegistry.Event _ stopped; -- not reported unless stateIsKnown is TRUE CurrentWalnutState: PUBLIC ENTRY PROC RETURNS[walnutState: WalnutRegistry.WalnutState] = { IF stateIsKnown THEN { IF stateIs=stopped THEN RETURN[stopped] ELSE RETURN[active] } ELSE RETURN[unknown]; }; 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 stateIsKnown 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 { stateIsKnown _ TRUE; 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.