FQImpl.mesa
Last Modified On November 9, 1983 10:09 am By Paul Rovner
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] =
usage: Bump[@stats.nHandleRCUnderflow];
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: BOOLTRUE] = {
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.