The GC Extent means all the objects that have been registered with the CSpace
.
Objects are registered in the CSpace
in order to support the sweep phase of the garbage collector.
In order for an object to be regarded as existing in a CSpace
it must be
explicitly registered with the CSpace
.
This is usually done immediately after the object is allocated.
An object can be registered in at most one CSpace
.
$adt+ CSpace
{
void RegisterGcObject(ptr<IObject> object);
void RegisterNonGcObject(ptr<IObject> object);
ssize_t GetNumObjects() const;
};
void RegisterGcObject(ptr object)
Adds an object to the set of objects to be garbage collected.
Requires a lock on this CSpace
.
The given object must be heap allocated and must not currently be registered with any CSpace
.
Ownership is transferred to the CSpace
so the object must not subsequently be deleted by the client.
RegisterNonGcObject(ptr object)
Object is marked as belonging to the CSpace
but will not be destroyed.
ssize_t GetNumObjects() const
Get the total number of objects in the CSpace
.
Must not be called on a CSpace
on which the garbage collector is enabled.
$function+ void RegisterGcObject(ptr<IObject> object)
{
if (CSpace* cs = GetThreadPtr<CSpace>())
{
RegisterGcObject(cs, object);
}
else
{
throw AssertionException("RegisterGcObject called without CSpace set in thread local storage");
}
}
$function+ void RegisterNonGcObject(ptr<IObject> object)
{
if (CSpace* cs = GetThreadPtr<CSpace>())
{
RegisterNonGcObject(cs, object);
}
else
{
throw AssertionException("RegisterNonGcObject called without CSpace set in thread local storage");
}
}
void RegisterNonGcObject(ptr<IObject> object)
RegisterNonGcObject()
sets the given object to be associated with the
CSpace
in thread local storage.
The CSpace
must be set in thread local storage, but it doesn't need to be locked.
This allows objects in the CSpace
to avoid being deleted by the GC.
This is appropriate for the following:
These objects can take part in the trace algorithm but they don't take part in the sweep phase. The implementation avoids recording them in the GC-extent. It also avoids marking them as visited (avoiding the problem of how to reset the visited flag at the start of each trace). However that means that a cycle amongst non-gc objects must be avoided or else the gc trace gets stuck in an infinite loop.
Xcpp converts expressions of the form $new X(args...)
into DollarNew(new X(args,...))
.
See $new.
template <typename T>
T* DollarNew(T* p)
{
RegisterGcObject(p);
return p;
}
template <typename T>
T gc(T p)
{
if (p) RegisterGcObject(p);
return p;
}
template <typename T>
ptr<IObject> CreateInstance()
{
ptr<IObject> p = GetReflectedClass<T>().m_createFn();
RegisterGcObject(p);
return p;
}
$struct+ ReflectedClass <<os compare>>
{
$ptr<IObject> Create() const
{
if (m_createFn)
{
ptr<IObject> p = m_createFn();
RegisterGcObject(p);
return p;
}
else return null;
}
};
$mixin RegisteredNonGcObject
{
$$()
{
CSpaceLock _;
RegisterNonGcObject( $this );
}
};