ValueTree, var and ContainerDeletePolicy


#1

Is there any particular reason that var doesn't use the ContainerDeletePolicy?  It'd be good if it did ... 


#2

It's because I'd never expect anyone to use a ScopedPointer<var> or OwnedArray<var>... in fact, I can't think of a good reason to ever heap-allocate a var! What's your reason for needing it?


#3

It's nothing to do with putting var on the heap. It's abot storage of ReferenceCountedObjects in vars and multi-threading.

I'm after a custom delete action (copy the object into a queue for deletion) for a set of ReferenceCountedObjects. Implementing a ContainerDeletePolicy<MyClass> was working fine when I had them in ReferenceCountedPtr<> but not when I store the ReferenceCountedObject in a var. 

 

 


#4

var

    void cleanUp (ValueUnion& data) const noexcept override   { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }

 

ReferenceCountedObjectPtr

    static void decIfNotNull (ReferencedType* o) noexcept

    {

        if (o != nullptr && o->decReferenceCountWithoutDeleting())

            ContainerDeletePolicy<ReferencedType>::destroy (o);

    }

 


#5

I don't think it'd even be possible, as the var only uses the ReferenceCountedObject base, whilst the policy stuff is all based on explicit typing via the template. I guess you could maybe wrap your objects in another object which holds an explicitly typed ReferenceCountedObjectPtr... though that might get a bit ugly!


#6

Yep, you're right. It need to know about the template, which it can't as it's in a separate .cpp file.  Awkward.  

I'd really like to get control of the action when the reference count hits zero though.  I'm about four lines of code away from an experimental lock-free ValueTree mirror for my audio thread ... which would be nice. 

An alternative would be a different type of ReferenceCountedObject.  Maybe  a virtual decrementCounter() function.  Is there a better way? 


#7

Ah! I thought you were talking about a ContainerDeletePolicy for deleting vars.

Ok, but there's nothing I could change there that would make any difference to this. The ReferenceCountedObjectPtr class knows the type of the object that's being deleted, so it can invoke a custom policy for your class. But var doesn't have any information about the derived type - if I changed it to call ContainerDeletePolicy<ReferenceCountedObject>::destroy, that would do exactly the same thing that it does now.


#8

Ok - if there's no obvious solution let me go and have a look at doing it with some kind of manager class that tracks the objects reference counts and deletes anything that gets to 1. 


#9

Ok.  That was a lot easier.  Seemingly good solution below.  

Pretend this forum thread never existed. 

class GrimReaper :

Timer {

public:

    juce_DeclareSingleton(GrimReaper, false)

    GrimReaper() {

        startTimer(250);

    }

    ~GrimReaper() {

        clearSingletonInstance();

        timerCallback();

        jassert(data.size() == 0);

    }

    void add(ReferenceCountedObject * o) {

        o->incReferenceCount();

        data.push_back(o);

    }

private:

    void timerCallback() {

        data.remove_if([](ReferenceCountedObject * o){

            if (o->getReferenceCount() == 1) {

                o->decReferenceCount(); /* Will delete it too! */

                return true;

            }

            return false;

        });

    }

    std::list<ReferenceCountedObject *> data;

};