<<>> <> <> <> <> <<>> <> <> <<>> DIRECTORY PropList, Xl, XlPerDepth; XlPerDepthImpl: CEDAR MONITOR IMPORTS PropList, Xl EXPORTS XlPerDepth ~ BEGIN OPEN XlPerDepth; <> <> <> <<>> dummy: REF PrivateRec ~ NEW[PrivateRec ¬ [sd: NEW[Xl.ScreenDepthRec], sdData: NIL]]; cDiedFilter: Xl.EventFilter ~ Xl.CreateEventFilter[finalEvent]; sharedTQ: Xl.TQ ¬ Xl.CreateTQ[]; ConnectionDied: Xl.EventProcType = { <<--Remove properties to break circular refs disabling finalization >> WITH event SELECT FROM fe: Xl.FinalEvent => IF ~fe.refCountTransition THEN { h: Handle ~ NARROW[clientData]; FOR i: NAT IN [0..Xl.ScreenDepthCount[event.connection]) DO sd: Xl.ScreenDepth ¬ Xl.NthScreenDepth[event.connection, i]; [] ¬ PropList.RemProp[sd.properties, h]; IF h.last.sd=sd THEN h.last ¬ dummy; ENDLOOP }; ENDCASE => {}; }; Init: PropList.InitializeProcType = { h: Handle ~ NARROW[key]; sd: Xl.ScreenDepth ~ NARROW[data]; sdData: REF ~ h.init[sd, h.initData]; pr: REF PrivateRec ~ NEW[PrivateRec ¬ [sd: sd, sdData: sdData]]; Xl.AddDispatch[sd.screen.connection, Xl.nullWindow, NEW[Xl.MatchRep ¬ [proc: ConnectionDied, handles: cDiedFilter, tq: sharedTQ, data: h]]]; RETURN [pr] }; GetData: PUBLIC PROC [h: Handle, sd: Xl.ScreenDepth] RETURNS [REF] = { pr: REF READONLY PrivateRec ¬ h.last; IF pr.sd=sd THEN RETURN [pr.sdData] ELSE { propList: PropList.List ~ IF sd=NIL OR ~Xl.Alive[sd.screen.connection] THEN PropList.NarrowPropList[h.implData] ELSE sd.properties; TRUSTED { pr ¬ NARROW[PropList.GetPropOrInit[propList, h, Init, LOOPHOLE[sd]].val]; }; h.last ¬ pr; RETURN [pr.sdData] }; }; InstallHandle: PUBLIC PROC [init: InitProc, initData: REF ¬ NIL] RETURNS [Handle] = { RETURN [NEW[HandleRep ¬ [last: dummy, initData: initData, init: init, implData: PropList.NewPropList[]]]] }; END.