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?