<> <> DIRECTORY Allocator, AllocatorOps, Process, RecursivelyNIL USING[NILRef, CheckProc], SafeStorage; TestRecursivelyNILImpl: PROGRAM IMPORTS AllocatorOps, Process, RecursivelyNIL, SafeStorage = BEGIN root: REF1 _ NIL; lastREF: CARDINAL = 19; REF1Rec: TYPE = RECORD [ I1: INT _ 33, C1: CARDINAL _ 2323, next: REF1 _ NIL, other: REF ANY, refs: ARRAY [0..lastREF] OF REF ANY _ ALL[NIL] ]; REF1: TYPE = REF REF1Rec; REF2Rec: TYPE = RECORD [ I2: REAL _ 33.33, C2: CARDINAL _ 2323, next: REF1 _ NIL, other: REF ANY ]; REF2: TYPE = REF REF2Rec; REF3Rec: TYPE = RECORD [ I2: REAL _ 33.33, C2: INT _ 2323 ]; REF3: TYPE = REF REF3Rec; REF4Rec: TYPE = RECORD [ rr: REF3 _ NIL ]; REF4: TYPE = REF REF4Rec; fiveTypeField: TYPE = {foo1, foo2}; REF5Rec: TYPE = RECORD [ varPart: SELECT tag: * FROM foo1 => [one: REF ANY _ NIL], foo2 => [ two: REF3 _ NIL, anINT: INT _ 3 ], ENDCASE ]; REF5: TYPE = REF REF5Rec; oneREF5: TYPE = foo1 REF5Rec; twoREF5: TYPE = foo2 REF5Rec; REF6Rec: TYPE = RECORD [ nRuns: CARDINAL _ 4, runs: SEQUENCE length: CARDINAL OF REF4]; REF6: TYPE = REF REF6Rec; REF7Rec: TYPE = RECORD [ the8: REF8 ]; REF7: TYPE = REF REF7Rec; REF8Rec: TYPE = RECORD [ the7: REF7 ]; REF8: TYPE = REF REF8Rec; REF7Type: SafeStorage.Type = CODE[REF7]; REF8Type: SafeStorage.Type = CODE[REF8]; BuildTest: PROC = { lastNext: CARDINAL = 249; current: REF1; current2: REF1; refIndex: CARDINAL _ 0; phase: BOOL _ FALSE; runSize: CARDINAL _ 2; root _ NEW[REF1Rec]; current _ root; FOR I:INT IN [0..lastNext] DO new: REF1 _ NEW[REF1Rec]; current.next _ new; current _ new; ENDLOOP; current _ root; FOR I:INT IN [0..lastNext] DO new: REF ANY _ NEW[REF3Rec]; IF phase THEN { new4: REF4 _ NEW[REF4Rec]; new4.rr _ NARROW[new]; new _ new4; }; current.other _ new; current _ current.next; phase _ ~phase; ENDLOOP; current _ root; current2 _ root; FOR I:INT IN [0..lastNext] DO nhp: Allocator.NHeaderP; i:INT _ 0 ; new: REF2 _ NEW[REF2Rec]; new5: REF5 _ NIL; new6: REF6 _ NIL; new7: REF7 _ NIL; new8: REF8 _ NIL; current.refs[refIndex] _ new; new7 _ NEW[REF7Rec]; new8 _ NEW[REF8Rec]; new.other _ new7; new8.the7 _ new7; new7.the8 _ new8; nhp _ AllocatorOps.REFToNHP[new7]; IF nhp.refCount # 2 THEN {i _ i + 1 }; SafeStorage.EnableFinalization[new7]; IF nhp.refCount # 1 THEN {i _ i + 1 }; refIndex _ refIndex + 1; IF refIndex > lastREF THEN refIndex _ 0 ; IF current2 = NIL THEN current2 _ root ELSE current2 _ current2.next; IF current2 = NIL THEN current2 _ root ELSE current2 _ current2.next; current.refs[refIndex] _ current2; refIndex _ refIndex + 1; IF refIndex > lastREF THEN refIndex _ 0 ; IF phase THEN { aNew3: REF3 _ NEW[REF3Rec]; new5 _ NEW[oneREF5 _ [foo1[one: aNew3]]]; } ELSE { aNew3: REF3 _ NEW[REF3Rec]; new5 _ NEW[twoREF5 _ [foo2[two: aNew3]]]; }; current.refs[refIndex] _ new5 ; refIndex _ refIndex + 1; IF refIndex > lastREF THEN refIndex _ 0 ; runSize _ runSize + 3; IF runSize > 14 THEN runSize _ 3 ; new6 _ NEW[REF6Rec[runSize]]; FOR i: CARDINAL IN [0..runSize) DO new6[i] _ NEW[REF4Rec _ [ rr: NEW[REF3Rec]]]; ENDLOOP; current.refs[refIndex] _ new6; refIndex _ refIndex + 1; IF refIndex > lastREF THEN refIndex _ 0 ; current _ current.next; phase _ ~phase; ENDLOOP; }; DestroyTest: PROC = { RecursivelyNIL.NILRef[root, checkIt]; root _ NIL ; }; AREFANY: REF ANY _ NIL; OneREF7Test: PROC = { i:INT _ 0 ; nhp: Allocator.NHeaderP; new7: REF7 _ NIL; new8: REF8 _ NIL; new7 _ NEW[REF7Rec]; new8 _ NEW[REF8Rec]; AREFANY _ new7; new8.the7 _ new7; new7.the8 _ new8; nhp _ AllocatorOps.REFToNHP[new7]; IF nhp.refCount # 2 THEN {i _ i + 1 }; SafeStorage.EnableFinalization[new7]; IF nhp.refCount # 1 THEN {i _ i + 1 }; }; checkIt: RecursivelyNIL.CheckProc = { <> IF objectREFType = REF7Type OR objectREFType = REF8Type THEN ERROR; IF referredREFType = REF7Type OR referredREFType = REF8Type THEN ERROR; }; fQ: SafeStorage.FinalizationQueue; Finalize: PROC = { ref7: REF7 _ NIL; DO ref7 _ NARROW[SafeStorage.FQNext[fQ] ]; ref7.the8 _ NIL; ref7 _ NIL; ENDLOOP; }; fQ _ SafeStorage.NewFQ[]; SafeStorage.EstablishFinalization[CODE[REF7Rec], 1, fQ]; TRUSTED { Process.Detach[FORK Finalize[]] }; END.