CSpace GC extent

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.

Methods of the CSpace to register objects in the GC extent

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.

Free functions that use the CSpace in thread local storage


$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.

Registration of object with CSpace using $new

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;
}

gc template function


template <typename T>
T gc(T p)
{
    if (p) RegisterGcObject(p);
    return p;
}

CreateInstance() template function


template <typename T>
ptr<IObject> CreateInstance()
{
    ptr<IObject> p = GetReflectedClass<T>().m_createFn();
    RegisterGcObject(p);
    return p;
}

Create() method of ReflectedClass


$struct+ ReflectedClass <<os compare>>
{
    $ptr<IObject> Create() const 
    { 
        if (m_createFn) 
        {
            ptr<IObject> p = m_createFn();
            RegisterGcObject(p);
            return p;
        }
        else return null; 
    }
};

Mixin to declare non-GC object


$mixin RegisteredNonGcObject
{
    $$()
    {
        CSpaceLock _;
        RegisterNonGcObject( $this );
    }
};