Buffer::setSize() : avoidReallocating flag not always respected


#1

from the doc :

If avoidReallocating is true, then changing the buffer’s size won’t reduce the
amount of memory that is currently allocated (but it will still increase it if
the new size is bigger than the amount it currently has). If this is false, then
a new allocation will be done so that the buffer uses takes up the minimum amount of memory that it needs.

But this is only true if the other flag ‘keepExistingContent’ is false.
if ‘keepExistingContent’ is true then ‘avoidReallocating’ is ignored and the memory is always reallocated.

So if I do :

bool keepContent = true;
bool clearExtra = false;
bool avoidRealloc = true;
buffer.setSize (buffer.getNumChannels(), buffer.getNumSamples() / 2,
                keepContent, clearExtra, avoidRealloc);

the buffer will be reallocated, while that’s not expected/necessary


#2

Hmm, it’s actually quite tricky to do that - if for example you changed the number of channels + samples but the size still fits, it could involve some extremely tricky remapping to rearrange the old data into its new layout using an in-place transform…


#3

hmm,I haven’t thought about that case…
Perhaps just modify the doc and add an assertion like that ?:

// we can't avoid reallocating while keeping existing content
jassert (! avoidReallocating || ! keepExistingContent);

just to make sure people call setSize (n, m, false, false, true)
and not setSize (n, m, true, false, true) if their priority is to avoid allocation ?


#4

Yeah… actually, thinking about it again, it might be quite easy to do, I’ll take a quick look.


#5

Thanks Jules.

Unless I’m missing a particular case, I think we could use the same trick to save some clear() calls in that bit too :

if (avoidReallocating && allocatedBytes >= newTotalBytes)
{
    if (clearExtraSpace || isClear)
    {
         allocatedData.clear (newTotalBytes);
    }
}

Because if there is no extra space allocated, or if the buffer is already cleared, then there is no need to clear the allocatedData again if the channels pointers don’t change.

if (avoidReallocating && allocatedBytes >= newTotalBytes)
{
    if (clearExtraSpace || isClear)
    {
        if (newNumChannels <= numChannels && newNumSamples <= size)
        {
            // no need to clear in that case, as the channel pointers will remain correct
        }
        else
        {
            allocatedData.clear (newTotalBytes);
        }
    }
}

#6

nice improvement, but there should also a jassert, when reallocating can’t be avoided.