FinalizeOps0.mesa
Copyright Ó 1989, 1991 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, December 1, 1989 4:15:02 pm PST
Christian Jacobi, July 20, 1992 12:36 pm PDT
This package is now outdated (Finalize now directly exports a client data field; all other features are not really difficult to implement on top of the improved Finalize)
FinalizeOps0: CEDAR DEFINITIONS
~ BEGIN
Implements some patterns how to deal with finalizable objects.
Mainly:
A method to create finalizable objects and put these into a table without the table preventing the finalization of the objects.
Passing of an extra ref to the finalization procedure.
Avoid using a process for the finalizations.
Limitations:
1: Don't use other finalization methods to revive objects handled by this package; this package wants to be sole finalization player for its objects.
2: Finalizable objects must not be part of circular structures.
When to use this module:
This package provides help for implementing some "medium level" complexity patterns for finalization. Trivial usage might, more complex usage must be done with PFinalize directly.
This module is particularly useful for the case it has been designed to help: when finalizable objects are to be cached in some table. In this case the module handles the subtle monitoring requirements for guaranteeing table inclusion to run parallel to finalization state.
When there are no "tables" (therefore no "uncounted" refs to objects), this module might be overkill and direct use of PFinalize could be recommended.
Object: TYPE = REF; --finalizable object
Key: TYPE = REF; --key used to find finalizable object in table, or, passed to creation/finalization
Context: TYPE = REF ContextRefRep; --handle; context or table containing finalizable objects
ContextRefRep: PRIVATE TYPE = REF ContextRep;
ContextRep: PRIVATE TYPE;
ContextKind: TYPE = {finalize, finalizeWithKey, finalizeWithRefTab, finalizeWithSymTabCase, finalizeWithSymTabNoCase};
finalize:
No table is used. The key plays the role of client data. It is passed to the create procedure, but NOT to the finalize procedure. Neither the hash nor the equal procedures are used.
This is a quite trivial usage of PFinalize; usage of this package is justified only for the saving of a process resource.
finalizeWithKey:
No table is used. The key plays the role of client data. It is passed to the create and the finalize procedures. Neither the hash nor the equal procedures are used.
finalizeWithRefTab:
The general case for this package. Object is included in table and removed when finalized.
The key is passed to the create and the finalize procedures.
equal defaults to key1=key2 (pointer equality)
hash defaults to BITXOR[HighHalf[key], LowHalf[key]]
finalizeWithSymTabCase:
Like finalizeWithRefTab; table is SymTab, case=TRUE. Wedges if key not rope.
Neither the hash nor the equal procedures are used.
finalizeWithSymTabNoCase:
Like finalizeWithRefTab; table is SymTab, case=FALSE. Wedges if key not rope.
Neither the hash nor the equal procedures are used.
CreateProc: TYPE = PROC [key: Key, contextData: REF] RETURNS [object: Object ¬ NIL];
Used by context for creation of new object.
Locks out any operation with "equal" keys on context [released on UNWIND].
Client must not fool with finalization of returned objects in independent modules [Could destroy internal package invariants of context].
FinalizeProc: TYPE = PROC [object: Object, key: Key, contextData: REF] RETURNS [reEnable: BOOL ¬ FALSE];
Used by context to require client finalization of object.
If "reEnable"=TRUE the finalization is denied; object is re-included into table/context and finalization is reenabled.
Better don't raise exceptions: Called within two locks:
1) Locks out creation of objects with "equal" keys in context.
2) Locks out all other finalizations of context.
EqualProc: TYPE = PROC [key1, key2: Key] RETURNS [BOOL];
Used by context to find out whether two keys denote same object.
Must not raise exceptions: would wedge context.
On purpose equal to RefTab.EqualProc
HashProc: TYPE = PROC [key: Key] RETURNS [CARDINAL];
Used by context to create a hash value for a key.
The following equality must hold: equal[k1, k2] => hash[k1]=hash[k2]
Must not raise exceptions: would wedge context.
On purpose equal to RefTab.HashProc
GetOrCreateObject: PROC [context: Context, key: Key ¬ NIL, create: CreateProc ¬ NIL] RETURNS [Object];
Gets finalizable object from table/context or creates a new object if none is found in table.
May return NIL if no object found in table/context and CreateProc returned NIL.
create: If non NIL, is used instead of contexts create proc. May be nested.
CreateContext: PROC [create: CreateProc ¬ NIL, equal: EqualProc ¬ NIL, hash: HashProc ¬ NIL, finalize: FinalizeProc ¬ NIL, contextData: REF ¬ NIL, kind: ContextKind ¬ finalizeWithRefTab, millisecondsBetweenChecks: INT ¬ 0] RETURNS [Context];
Creates new context/table for finalizable objects.
create: called to create objects.
equal, hash: for implementing RefTab-like table.
finalize: called for finalization. Defaults to {RETURN[FALSE]}
contextData: client data passed through to create and finalize
kind: see above.
millisecondsBetweenChecks: frequency for checking the finalization queue; 0 for good default value.
END.