[Issue 4681] Appender access violation

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Aug 26 05:51:25 PDT 2010


http://d.puremagic.com/issues/show_bug.cgi?id=4681



--- Comment #12 from Steven Schveighoffer <schveiguy at yahoo.com> 2010-08-26 05:51:15 PDT ---
(In reply to comment #11)
> This is still full of dirty runtime calls and attempts to emulate half of
> lifetime.d (though the worst part is commented).

Why are runtime calls dirty?  I don't use any undocumented runtime functions...

It doesn't emulate lifetime, except for the newCapacity function (which
arguably could be a call into the runtime, but it's a simple enough function,
and doesn't really have to be consistent with the runtime), and the use of
GC.extend.  I'm notably not trying to store the length inside the memory block.

> Why doesn't it simply use the D standard way to re-allocate an array, and then
> use array.capacity to see how much can be safely appended?

Because the call to the runtime cannot be inlined, and is much slower than
simply dereferencing a pointer.  Appender is supposed to be as fast as possible
at appending.

If you want to use built-in appending, just use it.  Appender is for getting
the highest possible performance out of an array.

> 
> Something along the lines of:
> 
> private struct Data {
>    T[] arr;
>    size_t user_length;
> }
> 
> Data _data;
> 
> void put(T item) {
>    if (_data.user_length == arr.length) {
>       size_t newcapacity = something larger than user_length;
>       reallocate(newcapacity);
>    }
>    _data.arr[_data.user_length++] = item;
> }
> 
> void reallocate(size_t newcapacity) {
>    _data.arr.length = newcapacity;
>    //include the data "overallocated" by the runtime into the array
>    size_t realcap = _data.arr.capacity;
>    _data.arr.length = realcap;
> }
> 
> T[] data() {
>    T[] arr = _data.arr[0.._data.user_length];
>    _data = _data.init;
>    assumeSafeAppend(arr);
>    return arr;
> }
> 
> Or did I overlook something.

This is a different way of doing it, though I'd probably replace reallocate
with a standard ~=.  I think your way would work fine.

I agree your way seems more congruent with the runtime.  I wonder if there are
any advantages to doing it that way?  I think the Appender I committed is going
to be slightly faster in the long run, because it avoids using runtime
appending at all.  However, it has some limitations in that it cannot use the
rest of a passed in memory block (i.e. the space beyond the initial array). 
But your code gave me an idea of how to achieve that.  I think this should
work:

this(T[] arr)
{
   _data = new Data;
   _data.arr = arr;
   auto cap = arr.capacity;
   if(cap > origlen)
      arr.length = cap; // use up the rest of the block
   _data.capacity = arr.length;
}

I'll add this change too.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------


More information about the Digitalmars-d-bugs mailing list