Stack-based @nogc dynamic array

Marco de Wild mdwild at sogyo.nl
Thu May 16 12:16:26 UTC 2019


Hey all,

I want to create a small collection of items to store 
intermediate results of a calculation. It runs on a background 
thread, so it does not need to be the most efficient 
implementation. However, I want to prevent my background thread 
introducing a stop-the-world garbage collection.
In my program (rules and an AI for a mahjong game), the 
collection size is at most 14 (tiles in hand). I figured it would 
be the most simple to just keep it stack based. MY first attempt 
looks like:
```
struct NoGcArray(size_t maxSize, T)
{
     private T[maxSize] _buffer;
     private size_t _length;
     size_t length() pure const @nogc nothrow
     {
         return _length;
     }

     void opOpAssign(string op)(T element) pure @nogc nothrow
     in(_length < maxSize, "Cannot append if the buffer is fully 
filled.")
     {
         static if(op == "~")
         {
             _buffer[_length] = element;
             ++_length;
         }
         else
         {
             static assert(false, "Only concatenation supported");
         }
     }

     T opIndex(size_t index)
     in(index < _length, "Cannot access index greater than length")
     {
         return _buffer[index];
     }

     auto range() pure const @nogc nothrow
     {
         return Range(this);
     }

     alias range this;

     static struct Range
     {
         this(NoGcArray src)
         {
             _src = src;
         }
         private NoGcArray _src;
         private size_t _index;

         T front() pure @nogc nothrow
         {
             return _src[_index];
         }

         void popFront() pure @nogc nothrow
         {
             _index++;
         }

         bool empty() pure @nogc nothrow
         {
             return _src._length <= _index;
         }
     }
}
```
However,
```
unittest
{
     import std.algorithm : sum, map;
     import fluent.asserts;
     NoGcArray!(4, int) array;
     array ~= 420;
     array ~= 42;
     array.map!(x => x*2).sum.should.equal(924);
}
```
fails. The test will run in an infinite loop. After some digging, 
I realise that the `alias this` is foiling with my plan rather 
than helping it. Is there a recommended way to achieve
- std.algorithm functions should Just Work (tm)
- appending as if it were a dynamic array
- preferably index-based access and .length should also work.

Is there a dub package that achieves this? Or are there any tips 
to roll my own implementation?


More information about the Digitalmars-d-learn mailing list