-- RTTypesBasicExtensionImpl.mesa -- Last Modified On May 27, 1982 4:29 pm by Paul Rovner DIRECTORY RTQueue USING[New, Dequeue, Empty, Q, qNil, Enqueue], RTTypesBasic USING[GetCanonicalType, FinalizationQueue, maxNPackageRefs, CantEstablishFinalization, Type], RTTypesBasicPrivate USING[RTypeExtension, PTypeExtension, PTypeDesc, MapTiTd, TypeExtension]; RTTypesBasicExtensionImpl: MONITOR -- protects list of type extensions IMPORTS RTQueue, RTTypesBasic, RTTypesBasicPrivate EXPORTS RTTypesBasic, RTTypesBasicPrivate = BEGIN OPEN RTTypesBasic, RTTypesBasicPrivate; -- private variables typeExtensions: RTypeExtension _ NIL; -- PUBLIC procedures -- Finalization of collectible objects; type attachments EstablishFinalization: PUBLIC ENTRY SAFE PROC [type: Type, npr: [1..maxNPackageRefs], fq: FinalizationQueue] = TRUSTED { ENABLE UNWIND => NULL; cType: Type = GetCanonicalType[type]; ptd: PTypeDesc _ MapTiTd[cType]; --NOTE beware of LOOPHOLED sharing!! IF ptd.extension = NIL THEN MapTiTd[type].extension _ ptd.extension _ CreateTypeExtension[]; IF (NOT npr IN [1..maxNPackageRefs]) OR ptd.extension.finalizationSet # NIL THEN ERROR CantEstablishFinalization[type]; MapTiTd[cType].nPackageRefs _ npr; MapTiTd[type].nPackageRefs _ npr; LOOPHOLE[ptd.extension, RTypeExtension].finalizationSet _ LOOPHOLE[fq]}; ReEstablishFinalization: PUBLIC ENTRY SAFE PROC [type: Type, npr: [1..maxNPackageRefs], fq: FinalizationQueue] = TRUSTED { ENABLE UNWIND => NULL; cType: Type = GetCanonicalType[type]; ptd: PTypeDesc _ MapTiTd[cType]; --NOTE beware of LOOPHOLED sharing!! IF ptd.extension = NIL THEN ERROR CantEstablishFinalization[type]; IF npr # ptd.nPackageRefs OR npr # MapTiTd[type].nPackageRefs OR ptd.extension.finalizationSet = NIL THEN ERROR CantEstablishFinalization[type]; LOOPHOLE[ptd.extension, RTypeExtension].finalizationSet _ LOOPHOLE[fq]}; NewFQ: PUBLIC SAFE PROC[length: CARDINAL _ 10--refs--] RETURNS[FinalizationQueue] = TRUSTED { RETURN[LOOPHOLE[RTQueue.New[length]]]}; FQNext: PUBLIC SAFE PROC[fq: FinalizationQueue] RETURNS[REF ANY] = TRUSTED { RETURN[RTQueue.Dequeue[LOOPHOLE[fq]]]}; -- WAITs till there is one if necessary FQEmpty: PUBLIC SAFE PROC[fq: FinalizationQueue] RETURNS[BOOLEAN] = TRUSTED { RETURN[RTQueue.Empty[LOOPHOLE[fq]]]}; PutTypeAttachment: PUBLIC ENTRY SAFE PROC[type: Type, attachment: REF ANY] = TRUSTED { ENABLE UNWIND => NULL; ptd: PTypeDesc = MapTiTd[GetCanonicalType[type]]; --NOTE beware of LOOPHOLED sharing!! IF ptd.extension = NIL THEN { MapTiTd[type].extension _ ptd.extension _ CreateTypeExtension[]}; LOOPHOLE[ptd.extension, RTypeExtension].attachment _ attachment; }; GetTypeAttachment: PUBLIC ENTRY SAFE PROC [type: Type] RETURNS[REF ANY] = TRUSTED { ENABLE UNWIND => NULL; ptd: PTypeDesc = MapTiTd[GetCanonicalType[type]]; --NOTE beware of LOOPHOLED sharing!! IF ptd.extension = NIL THEN RETURN[NIL] ELSE RETURN[LOOPHOLE[ptd.extension, RTypeExtension].attachment]; }; -- called only by the collector. NOTE this does no RC operations -- because if PutForFinalization succeeds the count is already correct PutForFinalization: PUBLIC PROC[type: Type, ref: REF ANY] RETURNS[done: BOOLEAN] = { ptd: PTypeDesc = MapTiTd[type]; q: RTQueue.Q; IF ptd = NIL OR ptd.extension = NIL OR (q _ ptd.extension.finalizationSet) = RTQueue.qNil THEN ERROR; RETURN[NOT RTQueue.Enqueue[q: q, ref: ref]]; }; -- PRIVATE procedures CreateTypeExtension: INTERNAL PROC RETURNS[PTypeExtension] = { ENABLE UNWIND => NULL; rte: RTypeExtension = NEW[TypeExtension _ [next: typeExtensions]]; typeExtensions _ rte; RETURN[LOOPHOLE[rte, PTypeExtension]]}; -- BEWARE NOTE this will be shared, and not w/ REFs END.