Order of Release/Resize Problem in ReferenceCountedArray


#1

I’ve run in to a bit of problem in ReferenceCountedArray, remove:

    void remove (int indexToRemove)
    {
        const ScopedLockType lock (getLock());

        if (isPositiveAndBelow (indexToRemove, values.size()))
        {
            auto** e = values.begin() + indexToRemove;
            releaseObject (*e);
            values.removeElements (indexToRemove, 1);

            if ((values.size() << 1) < values.capacity())
                minimiseStorageOverheads();
        }
    }

The problem is that the object is released before being removed from the array. So if in the destructor of the object being released I update some UI which also has a reference to the same array, it will return this object that is currently being destructed.

I think the values should be updated before the object is released?


#2

Hmm, I’m not sure that works actually but I’m not quite sure why…


#3

I can see the argument for removing then releasing.

What exactly are you doing in the destructor?


#4

The destructor calls some listeners to notify them that the objects are being deleted.
• Destructor of a MIDI clip calls listeners to notify them of destruction
• MIDI editor gets notified of the destruction
• This synchronously gets the clips to show via the ReferenceCountedArray
• That array still holds the clip currently being destroyed
• As a result, the now destroyed clip is still being shown in the editor and problems occur

N.B. I have worked around this using removeAndReturn as it doesn’t immediately destroy the object.

N.B. when I tried swapping the order of releaseObject and values.removeElements calls in the above remove call, I go all sorts of problems in ValueTree internal object reference counting. I didn’t have any time to dig in to this though so just used the removeAndReturn workaround I mentioned above.


#5

You can’t judt swap the order since then it’ll release whatever pointer in the array takes the place of the removed pointer. I think you need to store a pointer rather than double pointer.


#6