I’m trying to figure out how to manage Component object lifetime in Lua. Please see the pseudocode below. Is this the best way to manage JUCE object lifetime from a scripting language? I know I’m not the only person who’s done this.
My current approach is tracking ref counted pointers to Component objects by artificially incrementing ref counts by 1 on construction: thus, if there aren’t any Lua objects referencing it, it has a count of 1.
When a Lua object pointing to the Component gets garbage collected, it decrements as usual if it has a parent. If there is no parent and its own ref count is 2 (meaning this is the last Lua object referencing this Component), this is a chance to remove one or more objects that are no longer being referenced: it removes all subobjects that aren’t referenced as descendents by another Lua object. E.g.: A non-root Component has children of its own, and its referenced by a Lua object. When the root of this tree is destroyed, the remaining Lua object still points to the control, with its children, but has no parent.
When referencing an already created Component, it just gets ref counted as usual.
// Make Component class ref countable
class ComponentRC : public Component, public ReferenceCountedObject
{
// ...
};
// Lua interface wrapper used by my LuaCppObject class
class ComponentWrapper
{
public:
ComponentWrapper() : m_object(new ComponentRC())
{
m_object->incReferenceCount(); // keep minimum of 1 count
}
ComponentWrapper(ReferenceCountedObjectPointer<ComponentRC> & object)
{
m_object = object;
}
~ComponentWrapper()
{
if (m_object->getParentComponent() == nullptr && m_object->getReferenceCount() == 2)
{
deleteAllUnreferencedChildren(m_object);
m_object->decReferenceCount();
}
}
void deleteAllUnreferencedChildren(ComponentRC * object)
{
// Delete all children who have a ref count == 1 and do not hav a parent with ref count > 1
}
static int getChild(lua_State * L)
{
int const index = ...; // pop the index from the Lua state
ReferenceCountedObjectPointer<ComponentRC> rcComp(dynamic_cast<ComponentRC>(m_object->getChildComponent(index)));
// push object on lua stack
LuaCppObject<ComponentWrapper>::push(new ComponentWrapper(rcComp));
return 1;
}
// ... other methods, registration boilerplate
private:
ReferenceCountedObjectPointer<ComponentRC> m_object;
};