<> <> <> <> <> <<>> DIRECTORY Atom, Xl, XlPrivateTypes, XlFinalizePrivate; XlFinalizePrivateImpl: CEDAR MONITOR IMPORTS Atom, Xl EXPORTS Xl, XlPrivateTypes, XlFinalizePrivate = BEGIN ConnectionPrivate: PUBLIC <> TYPE = XlPrivateTypes.ConnectionPrivateImplRec; FinalizationRep: PUBLIC <> TYPE = FinalizationRec; FinalizationRec: TYPE = RECORD [ finalMatch: Xl.Match ¬ NIL, finalizationTQ: Xl.TQ ¬ NIL, countList: Atom.PropList ¬ NIL ]; Init: PUBLIC PROC [c: Xl.Connection, finalMatch: Xl.Match ¬ NIL] = { cPriv: REF XlPrivateTypes.ConnectionPrivateImplRec ¬ c.cPriv; cPriv.finalizationStuff ¬ NEW[FinalizationRec ¬ [ finalMatch: finalMatch, finalizationTQ: Xl.CreateTQ[], countList: Atom.PutPropOnList[NIL, NIL, NEW[CARD ¬ 1]] ]]; }; <<>> FinalizationStuff: PROC [c: Xl.Connection] RETURNS [REF FinalizationRec ¬ NIL] = { IF c#NIL THEN { cPriv: REF XlPrivateTypes.ConnectionPrivateImplRec ¬ c.cPriv; IF cPriv#NIL THEN RETURN [cPriv.finalizationStuff]; }; }; IncRefCount: PUBLIC ENTRY PROC [c: Xl.Connection, object: REF ¬ NIL] = { finalizationStuff: REF FinalizationRec ~ FinalizationStuff[c]; IF finalizationStuff#NIL THEN { count: REF CARD ¬ NARROW[Atom.GetPropFromList[finalizationStuff.countList, object]]; IF count#NIL THEN count­ ¬ count­+1 ELSE finalizationStuff.countList ¬ Atom.PutPropOnList[finalizationStuff.countList, object, NEW[CARD ¬ 1]]; }; }; <<>> DecRefCount: PUBLIC ENTRY PROC [c: Xl.Connection, object: REF ¬ NIL] = { finalizationStuff: REF FinalizationRec ~ FinalizationStuff[c]; IF finalizationStuff#NIL THEN { count: REF CARD ¬ NARROW[Atom.GetPropFromList[finalizationStuff.countList, object]]; IF count#NIL THEN { IF count­#1 THEN count­ ¬ count­ - 1 ELSE finalizationStuff.countList ¬ Atom.RemPropFromList[finalizationStuff.countList, object]; }; IF finalizationStuff.countList=NIL THEN { <<--fork to leave monitor and to be on right tq>> tq: Xl.TQ; finalMatch: Xl.Match ~ finalizationStuff.finalMatch; IF finalMatch#NIL THEN tq ¬ finalMatch.tq; IF tq=NIL THEN tq ¬ finalizationStuff.finalizationTQ; Xl.Enqueue[tq: tq, proc: TryCloseConnection, data: c]; }; }; }; TryCloseConnection: Xl.EventProcType = { c: Xl.Connection ~ NARROW[clientData]; finalizationStuff: REF FinalizationRec ~ FinalizationStuff[c]; IF finalizationStuff.countList=NIL THEN { finalMatch: Xl.Match ~ finalizationStuff.finalMatch; IF finalMatch#NIL THEN { proc: Xl.EventProcType ¬ finalMatch.proc; IF proc#NIL THEN { event: REF Xl.EventRep.finalEvent ¬ NEW[Xl.EventRep.finalEvent]; event.connection ¬ c; event.refCountTransition ¬ TRUE; proc[event, finalMatch.data, tq]; }; }; IF finalizationStuff.countList=NIL THEN Xl.CloseConnection[c]; }; }; END.