Static Public Member Functions |
static void * | operator new (size_t bytes) |
| Allocate memory.
|
static void * | operator new (size_t, void *where) |
| Placement new for GCNode.
|
static void | operator delete (void *p, size_t bytes) |
| Deallocate memory.
|
static bool | check () |
| Integrity check.
|
template<class T > |
static T * | expose (T *node) |
| Record that construction of a node is complete.
|
static void | gc () |
| Initiate a garbage collection.
|
static void | gclite () |
| Lightweight garbage collection.
|
static void | maybeCheckExposed (const GCNode *node) |
| Subject to configuration, check that a GCNode is exposed.
|
static size_t | numNodes () |
| Number of GCNode objects in existence.
|
Base class for objects managed by the garbage collector.
Abstract base class for all objects managed by the garbage collector.
- Derived class checklist:
- Classes derived directly or indirectly from GCNode should do the following to ensure the integrity of the garbage collection scheme:
-
Explicitly declare a destructor (even if it does nothing) as either protected or (if no further derivation from the class is envisaged) private. This ensures that objects of classes derived from GCNode can be created only using 'new'.
-
If the derived class contains any pointers or references to other objects derived from GCNode, these should be encapsulated within an object of the templated class GCEdge, and the class should reimplement the methods detachReferents() and visitReferents() appropriately. (This does not necessarily apply to pointers where other logic ensures that the pointer does not outlive the thing pointed to.)
- Infant immunity:
- Mark-sweep garbage collection is disabled while any GCNode or object of a class derived from GCNode is under construction. This greatly simplifies the coding of the constructors. Such an object is considered to be under construction from the moment the constructor is invoked until the node is exposed by calling the member function expose() (in one of its two forms), or until the node is deleted, whichever is sooner. It is the responsibility of any code that creates an object of a class derived from GCNode to ensure that the object is exposed as soon as possible, e.g. before a pointer to the node is returned as the value of a function. In particular, a node must be exposed before it is designated as the target of a GCEdge, a GCStackRoot or a GCRoot, or protected with PROTECT() or REPROTECT(): if the preprocessor variable CHECK_EXPOSURE is defined, runtime checks for this are inserted into the code.
The simplest way of ensuring timely exposure is always to wrap the new
call in a call to expose(): e.g. GCNode::expose(new FooNode(args)
. This can be further simplified using the CXXR_NEW macro to CXXR_NEW(FooNode).
- Note:
- Because this base class is used purely for housekeeping by the garbage collector, and does not contribute to the 'meaning' of an object of a derived class, its data members are mutable.
- Todo:
- The (private) cleanup() method needs to address the possibility that derived classes may have destructors that release some external resource (e.g. a lock). Maybe a garbage collection without a 'mark' phase would do the trick.
virtual void CXXR::GCNode::detachReferents |
( |
| ) |
|
|
inlinevirtual |
Null out all references from this node to other nodes.
The referents of this node are those objects (derived from GCNode) designated by a GCEdge within this object. This function changes all GCEdges within this object to encapsulate a null pointer. It is used during the sweep phase of a mark-sweep garbage collection to break up unreachable subgraphs, and in particular to remove reference loops from them. After the application of this method, the GCNode should be regarded as a 'zombie', kept in existence only so other nodes can detach their references to it cleanly (using decRefCount()).
- Note:
- If this method is reimplemented in a derived class, the reimplemented version must remember to invoke detachReferents() for the immediate base class of the derived class, to ensure that all referents of the object get detached.
Reimplemented in CXXR::Frame, CXXR::RObject, CXXR::Environment, CXXR::ConsCell, CXXR::Provenance, CXXR::ArgMatcher, CXXR::Symbol, CXXR::FixedVector< T, ST, Initializer >, CXXR::Closure, CXXR::WeakRef, CXXR::ExternalPointer, CXXR::Promise, CXXR::HandleVector< T, ST >, and CXXR::CommandChronicle.
template<class T >
static T* CXXR::GCNode::expose |
( |
T * |
node | ) |
|
|
inlinestatic |
Record that construction of a node is complete.
In normal operation (i.e. unless the object's constructor throws an exception), this function - or its non-templated form - should be called for each object derived from GCNode, and this should be done as soon as possible after construction of the object is complete. In particular, a node must be exposed before it is designated as the target of a GCEdge, a GCStackRoot or a GCRoot, or protected with PROTECT() or REPROTECT(): if the preprocessor variable CHECK_EXPOSURE is defined, runtime checks for this are inserted into the code.
The simplest way of ensuring timely exposure is always to wrap the new
call in a call to expose(): e.g. GCNode::expose(new FooNode(args)
. This can be further simplified using the CXXR_NEW macro to CXXR_NEW(FooNode).
It is not permissible for a node to be exposed more than once, and this is checked unless NDEBUG
is defined.
- Template Parameters:
-
T | GCNode or any class derived from it, possibly qualified by const. |
- Parameters:
-
node | Pointer to the node whose construction has been completed. |
- Returns:
- the pointer node itself.
- Note:
- The name of this function reflects an earlier design in which GCNode objects were individually exposed to mark-sweep garbage collection once their construction was complete. In the current design, mark-sweep garbage collection is inhibited entirely whilst any GCNode object is under construction.
static void CXXR::GCNode::maybeCheckExposed |
( |
const GCNode * |
node | ) |
|
|
inlinestatic |
Subject to configuration, check that a GCNode is exposed.
Normally, this function is an inlined no-op. However, if the preprocessor variable CHECK_EXPOSURE is defined, it checks that a GCNode is exposed to garbage collection, and aborts the program if not. This can be a useful diagnostic aid.
- Parameters:
-
node | Pointer to the node to be checked, or a null pointer in which case the check passes. |
virtual void CXXR::GCNode::visitReferents |
( |
const_visitor * |
v | ) |
const |
|
inlinevirtual |
Conduct a visitor to the nodes referred to by this one.
The referents of this node are those objects (derived from GCNode) designated by a GCEdge within this object.
- Parameters:
-
v | Pointer to the visitor object. |
- Note:
- If this method is reimplemented in a derived class, the reimplemented version must remember to invoke visitReferents() for the immediate base class of the derived class, to ensure that all referents of the object get visited. It is suggested that implementations set up stack-based pointers to all the referents of a node before visiting any of them; in that case, if the (recursive) visiting pushes the node out of the processor cache, there is no need to fetch it back in.
Reimplemented in CXXR::Frame, CXXR::RObject, CXXR::Environment, CXXR::ConsCell, CXXR::Provenance, CXXR::ArgMatcher, CXXR::Symbol, CXXR::FixedVector< T, ST, Initializer >, CXXR::Closure, CXXR::ExternalPointer, CXXR::Promise, CXXR::HandleVector< T, ST >, and CXXR::CommandChronicle.