On 12/17/20 1:10 PM, IGotD- wrote:
On Thursday, 17 December 2020 at 17:46:59 UTC, Steven Schveighoffer wrote:

This isn’t correct. Can you post the code that led you to believe this?

-Steve

Sure.


import std.algorithm;
import std.typecons;
import std.stdio;


struct Buffer
{
     this(size_t size)
     {
         m_buffer.reserve = size;
     }


     void add(const void[] arr)
     {
         m_buffer ~= cast(ubyte[])arr;
     }


     string getSome()
     {
         if(m_buffer.length > 0)
         {
             return cast(string)m_buffer[0..$];
         }
         else
         {
             return "";
         }
     }

     void remove(size_t size)
     {
         m_buffer = m_buffer.remove(tuple(0, size));

Here is where your issue is. It looks like you are removing the first size elements of the array. Which moves all the rest to the front. However, the array runtime still thinks you have the original number of elements in the buffer.

You need to add:

m_buffer.assumeSafeAppend;

This tells the runtime "I'm done with all the elements that are beyond this length."

And then it will work as you expect, no reallocation.

     }

     ubyte[] m_buffer;
}

void main()
{
     Buffer b = Buffer(16);

     b.add("aa");

    writeln("b.m_buffer.length ", b.m_buffer.length, ", b.m_buffer.capacity ", b.m_buffer.capacity);

     string s = b.getSome();

     assert(s == "aa");

     b.remove(s.length);

    writeln("b.m_buffer.length ", b.m_buffer.length, ", b.m_buffer.capacity ", b.m_buffer.capacity);
}

This will print

b.m_buffer.length 2, b.m_buffer.capacity 31
b.m_buffer.length 0, b.m_buffer.capacity 0

capacity 0, suggests that the array has been deallocated.

This means it has 0 capacity for appending according to the runtime, NOT that the array was deallocated. This is true of non-GC allocated slices and slices which don't END at the array end.

For example:

auto arr = [1, 2, 3];

auto arr2 = arr[0 .. 2]; // slice off the last element

assert(arr2.capacity == 0);
assert(arr.capacity != 0);

Does this mean the array is deallocated? No, it means that if you append, there is no capacity to add to. A capacity of 0 means "will reallocate if you append".

Why does this happen? Because we don't want to stomp on the existing data that could still be referenced via another slice (in this case arr) that still points to the original data.

You can read a bit about the array runtime here: https://dlang.org/articles/d-array-article.html

-Steve

Reply via email to