<> <> DIRECTORY Allocator USING[NHeaderP], AllocatorOps USING[REFToNHP, NHPToREF], RCMicrocodeOps USING[ZCTFull], RefQueue USING[Queue, IsFull, Enqueue], RTTypesBasicPrivate USING[NumberPackageRefs, MapTiTd], SafeStorage USING[], -- EXPORT of ClearFinalizedFlag ZCT USING[DoEnableFinalization, DisableFinalization, ExpandZCT]; FQImpl: MONITOR -- protects nhp.f IMPORTS AllocatorOps, RCMicrocodeOps, RefQueue, RTTypesBasicPrivate, ZCT EXPORTS SafeStorage, ZCT = BEGIN OPEN Allocator, AllocatorOps, RefQueue, RTTypesBasicPrivate; -- Statistics Count: TYPE = INT; takingStatistics: BOOL = TRUE; Bump: PROC[p: POINTER TO Count, delta: Count _ 1] = <> INLINE {IF takingStatistics THEN p^ _ p^+delta}; StatsRec: TYPE = RECORD [ nEnableFinalization: Count _ 0, nIsFinalizationEnabled: Count _ 0, nTryToQItForFinalization: Count _ 0, nZCTFull: Count _ 0, nQueueFull: Count _ 0, nAlreadyEnabled: Count _ 0 ]; stats: StatsRec _ []; -- the one and only EnableFinalization: PUBLIC ENTRY SAFE PROC[ref: REF] = TRUSTED{ ENABLE UNWIND => NULL; Bump[@stats.nEnableFinalization]; DO { nhp: NHeaderP = REFToNHP[ref]; IF nhp.f THEN {Bump[@stats.nAlreadyEnabled]; RETURN}; ZCT.DoEnableFinalization[NumberPackageRefs[LOOPHOLE[nhp.type]], nhp ! RCMicrocodeOps.ZCTFull => GOTO zctFull]; RETURN; EXITS zctFull => {Bump[@stats.nZCTFull]; ZCT.ExpandZCT[]}; }; ENDLOOP; }; IsFinalizationEnabled: PUBLIC ENTRY SAFE PROC[ref: REF] RETURNS[BOOL] = TRUSTED{ ENABLE UNWIND => NULL; Bump[@stats.nIsFinalizationEnabled]; RETURN[REFToNHP[ref].f]; }; TryToQItForFinalization: PUBLIC ENTRY PROC[nhp: NHeaderP] RETURNS[success: BOOL _ TRUE] = { ENABLE UNWIND => NULL; npr: NAT = NumberPackageRefs[LOOPHOLE[nhp.type]]; q: Queue = LOOPHOLE[MapTiTd[nhp.type].extension.finalizationSet]; Bump[@stats.nTryToQItForFinalization]; IF q.IsFull[] THEN {Bump[@stats.nQueueFull]; RETURN[FALSE]}; ZCT.DisableFinalization[npr, nhp]; IF q.Enqueue[NHPToREF[nhp]].full THEN ERROR; }; END.