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. < WalnutRegistryImpl.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Donahue, July 9, 1985 1:23:55 pm PDT Willie-Sue, December 29, 1986 5:57:23 pm PST Walnut Registry provides notification to outside clients of changes in Walnut databases. Walnut RegistryImpl can be run without running Walnut -- WalnutKernel imports it, rather than the other way around. Procedures registered with Walnut Registry are placed on the queue, using MBQueue.QueueClientAction, given in the registration when the database changes; clients are guaranteed that the procedures will be queued in the order in which the database changes that caused their invocation occurred. the values in the table are the registration entries; the keys are the Registrations returned (they are simply REF CARDINALS) the registrations are also linked into doubly-linked lists according to the type of procedures we want to be able to notify new clients of the current state of Walnut stitch it into the appropriate lists The heads to be non-NIL to make the list manipulation easier and faster Κΰ•NewlineDelimiter –(cedarcode) style™šΟb™Jšœ Οeœ6™BJ™$Icode™,J™J™ΝJ™J™₯—K˜šΟk ˜ Kšœ˜K˜KšœŸœŸœ˜Kšœ˜K˜Kšœ˜—K˜šœŸœŸ˜!K˜KšŸœ˜&KšŸœ&˜-K˜KšœŸ˜K˜KšœŸœŸœ˜1K˜KšœŸœŸœ3ŸœŸœ ŸœŸœ Ÿœ˜ΫK˜KšœŸœŸœ˜+K˜Kš œŸœŸœ ŸœŸœY˜‹K˜KšœŸœŸœ˜'K˜Kš œŸœŸœ ŸœŸœU˜…K˜KšœŸœŸœ˜)K˜Kš œŸœŸœ ŸœŸœW˜ˆK˜KšœŸœŸœ˜)K˜Kš œŸœŸœ ŸœŸœ[˜ŒK˜KšœŸœŸœ˜-K˜Kš œŸœŸœ ŸœŸœ[˜ŽK˜KšœŸœ˜K˜Kšœ0˜0Jšœ}™}K˜Jšœ^™^K˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜K˜J™GK˜(K˜šΟnœŸœŸœŸ˜%KšœŸœ-˜5šŸœ Ÿ˜Kšœ Ÿœ ˜KšœŸœ˜%Kšœ Ÿœ ˜KšŸœŸœ ˜—K˜—K˜š  œŸœŸœŸœ9Ÿœ/˜ŠKšœŸœ&˜GKšœŸœŸœ˜0K˜&K˜=Jšœ$™$šŸœŸœŸœ˜!KšœŸœc˜{K˜(K˜-K˜-K˜(šŸœŸ˜šœ"˜"Kšœ;˜;——Kšœ˜—šŸœŸœŸœ˜KšœŸœ]˜sK˜$K˜)K˜)K˜&—šŸœŸœŸœ˜ KšœŸœ`˜wK˜&K˜+K˜+K˜(—šŸœŸœŸœ˜$KšœŸœd˜K˜*K˜/K˜/K˜,—šŸœŸœŸœ˜"KšœŸœb˜{K˜*K˜/K˜/K˜,—Kšœ˜—K˜KšœŸœŸœŸœ˜)K˜š  œŸœŸœŸœ0˜MKšœŸœ4˜UKšŸœ ŸœŸœŸœ˜.šŸœŸœŸœ˜K˜1K˜1KšœŸœ˜—šŸœŸœŸœ˜K˜-K˜-KšœŸœ˜—šŸœŸœŸœ˜K˜/K˜/KšœŸœ˜—šŸœŸœŸœ˜"K˜7K˜7KšœŸœ˜"—šŸœŸœŸœ˜ K˜3K˜3KšœŸœ˜ —K˜6—K˜š  œŸœŸœŸœ,Ÿœ;˜‰KšœŸœ4˜UKšŸœ ŸœŸœŸœ˜.K˜šŸœŸœŸœ˜K˜)K˜5—šŸœŸœŸœ˜K˜%K˜0—šŸœŸœŸœ˜K˜'K˜2—šŸœŸœŸœ˜"K˜/K˜6—šŸœŸœŸœ˜ K˜+K˜1—Kšœ˜—K˜š  œŸœŸ œŸœŸœ˜DKšœŸœŸœ˜)—K˜š  œŸœŸœŸœ Ÿœ˜JKšœ ŸœŸœ Ÿœ˜6šŸœ0Ÿœ ŸœŸ˜HKšœO˜OKšŸœ˜ ——K˜š  œŸœŸœŸœ.ŸœŸœ˜cšŸœ,Ÿœ ŸœŸ˜DKšœZ˜ZKšŸœ˜ ——K˜š  œŸœŸœŸœ ŸœŸœŸœ˜QšŸœ.Ÿœ ŸœŸ˜FKšœ[˜[KšŸœ˜ ——K˜š  œŸœŸœŸœHŸœ˜uKšœŸœŸœ˜IK˜šŸœ.Ÿœ ŸœŸ˜FKšœe˜eKšŸœ˜ ——K˜š  œŸœŸœŸœ7ŸœŸœ˜ošŸœ2Ÿœ ŸœŸ˜JKšœc˜cKšŸœ˜ ——K˜JšœG™GKšœŸœ ŸœŸœ˜DK˜8K˜KšœŸœŸœŸœ˜@K˜2K˜KšœŸœŸœŸœ˜BK˜5K˜KšœŸœŸœŸœ˜BK˜5K˜KšœŸœ!ŸœŸœ˜FK˜;K˜KšŸœ˜—K˜—…— Ψ,τ