Feature suggestion: in-place append to array

Steven Schveighoffer schveiguy at yahoo.com
Thu Mar 4 10:18:53 PST 2010


On Thu, 04 Mar 2010 12:43:32 -0500, grauzone <none at example.net> wrote:

> Steven Schveighoffer wrote:
>> On Thu, 04 Mar 2010 11:43:27 -0500, grauzone <none at example.net> wrote:
>>
>>> Some sort of "resetAndReuse" function to clear an array, but enabling  
>>> to reuse the old memory would be nice:
>>>
>>> int[] a = data;
>>> a = null;
>>> a ~= 1; //reallocates (of course)
>>> a.length = 0;
>>> a ~= 1; //will reallocate (for safety), used not to reallocate
>>> resetAndReuse(a);
>>> assert(a.length == 0);
>>> a ~= 1; //doesn't reallocate
>>>
>>> This can be implemented by setting both the slice and the internal  
>>> runtime length fields to  0.
>>>
>>> Additionally, another function is necessary to replace the old  
>>> preallocation trick:
>>>
>>> //preallocate 1000 elements, but don't change actual slice length
>>> auto len = a.length;
>>> a.length = len + 1000;
>>> a.length = len;
>>>
>>> As I understood it, this won't work anymore after the change. This can  
>>> be implemented by enlarging the array's memory block without touching  
>>> any length fields.
>>>
>>> I'm sure the function you had in mind does one of those things or both.
>>  proposed usage (as checked in a couple days ago):
>>  int[] a;
>> a.setCapacity(10000); // pre-allocate at least 10000 elements.
>> foreach(i; 0..10000)
>>    a ~= i; // no reallocation
>> a.length = 100;
>> a.shrinkToFit(); // resize "allocated" length to 100 elements
>> a ~= 5; // no reallocation.
>
> What shrinkToFit() does is not really clear. Does it reallocate the  
> memory block of the array such, that no space is wasted? Or does it  
> provide (almost) the same functionality as my resetAndReuse(), and make  
> the superfluous trailing memory available for appending without  
> reallocation?

Sorry, should have added:

assert(a.length == 101);

Basically, shrinkToFit shrinks the "allocated" space to the length of the  
array. To put it another way, you could write your resetAndReuse function  
as follows:

void resetAndReuse(T)(ref T[] arr)
{
   arr.length = 0;
   arr.shrinkToFit();
}

I want to avoid assuming that shrinking the length to 0 is the only usable  
idiom.

>
> I think a resetAndReuse is really needed. I have found it can prevent  
> "GC thrashing" in many cases. E.g. when caching frequently re-evaluated  
> data in form of arrays (free previous array, then allocate array that  
> isn't larger than the previous array).

Yes, it is useful in such cases.  The only questionable part about it is  
that it allows for stomping in cases like:

auto str = "hello".idup;
auto str2 = str[3..4];
str2.shrinkToFit();
str2 ~= "a";
assert(str == "hella");

So it probably should be marked as unsafe.

Again, the name shrinkToFit isn't my favorite, ideas welcome.

-Steve



More information about the Digitalmars-d mailing list