RCArray is unsafe
Zach the Mystic via Digitalmars-d
digitalmars-d at puremagic.com
Thu Mar 5 08:11:25 PST 2015
On Wednesday, 4 March 2015 at 18:05:52 UTC, Zach the Mystic wrote:
> On Wednesday, 4 March 2015 at 17:22:15 UTC, Steven
> Schveighoffer wrote:
>> Again, I think this is an issue with the expectation of
>> RCArray. You cannot *save* a ref to an array element, only a
>> ref to the array itself, because you lose control over the
>> reference count.
>
> What you need is a special RCSlave type, which is reference
> counted not to the type of its *own* data, but to its parent's.
> In this case, a RCArraySlave!(T) holds data of type T, but a
> pointer to an RCArray, which it decrements when it gets
> destroyed. This could get expensive, with an extra pointer per
> instance than a regular T, but it would probably be safe.
A way to do this is to have a core RCData type which has the
count itself and the chunk of memory the count refers to in type
ambiguous form:
struct RCData {
int count;
// the point is that RCData can be type ambiguous
void[] chunk;
this(size_t size)
{
chunk = new void[size];
count = 0;
}
void addRef() {
++count;
}
void decRef() {
if (count && --count == 0)
delete chunk;
}
}
Over top of that you create a basic element type which refcounts
an RCData rather than itself:
struct RCType(E) {
E element;
RCType* data;
this(this)
{
data.addRef();
}
~this()
{
data.decRef();
}
[...etc...]
}
Then you have an RCArray which returns RCType elements when
indexed rather than naked types:
struct RCArray(E) {
E[] array;
private RCData* data;
RCElement!E opIndex(size_t i) return
{
return RCElement!E(array[start + i], data);
}
this(E[] a)
{
data = new RCData(a * sizeof(a));
array = cast(E[]) data.chunk;
}
this(this)
{
data.addRef();
}
~this()
{
data.decRef();
}
//...
}
This might work. The idea is to only leak references to types
which also have pointers to the original data.
More information about the Digitalmars-d
mailing list