<> <> <> <> <> <> <<>> DIRECTORY CountedVM USING [Handle, Object], Process USING [Detach, MsecToTicks, Pause], SafeStorage USING [CantEstablishFinalization, EnableFinalization, EstablishFinalization, FinalizationQueue, FQNext, NewFQ, ReclaimCollectibleObjects, ReEstablishFinalization], VM USING [AddressForPageNumber, Allocate, CantAllocate, Free, Interval, LogPageCount, nullInterval, PageCount, PagesForWords, PageNumber, VMPartition]; CountedVMImpl: CEDAR MONITOR IMPORTS Process, SafeStorage, VM EXPORTS CountedVM ~ BEGIN Handle: TYPE ~ CountedVM.Handle; Object: TYPE ~ CountedVM.Object; tries: NAT _ 4; <<# of times to try to collect extra garbage before giving up>> Allocate: PUBLIC PROC [words: INT, partition: VM.VMPartition _ normalVM, subRange: VM.Interval _ [0, 0], start: VM.PageNumber _ 0, alignment: VM.LogPageCount _ 0, in64K: BOOL _ FALSE] RETURNS [h: Handle _ NIL] = { IF words > 0 THEN TRUSTED { count: VM.PageCount ~ VM.PagesForWords[words]; FOR i: NAT IN [0..tries] DO interval: VM.Interval ~ VM.Allocate[count: count, partition: partition, subRange: subRange, start: start, alignment: alignment, in64K: in64K ! VM.CantAllocate => { <> IF i = tries THEN REJECT; SafeStorage.ReclaimCollectibleObjects[suspendMe: TRUE, traceAndSweep: FALSE]; Process.Pause[Process.MsecToTicks[200]]; LOOP; }]; h _ NEW[Object _ [interval: interval, pointer: VM.AddressForPageNumber[interval.page], words: words]]; SafeStorage.EnableFinalization[h]; EXIT; ENDLOOP; }; }; SimpleAllocate: PUBLIC PROC [words: INT] RETURNS [Handle] = { RETURN[Allocate[words: words]]; }; Free: PUBLIC ENTRY UNSAFE PROC [handle: Handle] = { ENABLE UNWIND => NULL; IF handle # NIL AND handle.pointer # NIL AND handle.words # 0 THEN { <> interval: VM.Interval _ handle.interval; handle.pointer _ NIL; handle.words _ 0; handle.interval _ VM.nullInterval; TRUSTED {VM.Free[interval]}; }; }; finalizationQueue: SafeStorage.FinalizationQueue _ SafeStorage.NewFQ[]; FinalizationProcess: PROC ~ { DO h: Handle _ NARROW[SafeStorage.FQNext[finalizationQueue]]; TRUSTED {Free[h]}; h _ NIL; ENDLOOP; }; SafeStorage.EstablishFinalization[Object.CODE, 0, finalizationQueue ! SafeStorage.CantEstablishFinalization => { SafeStorage.ReEstablishFinalization[Object.CODE, 0, finalizationQueue]; CONTINUE; }]; TRUSTED {Process.Detach[FORK FinalizationProcess]}; END.