Two suggestions for safe refcounting

Zach the Mystic via Digitalmars-d digitalmars-d at puremagic.com
Fri Mar 6 14:24:17 PST 2015


On Friday, 6 March 2015 at 14:59:46 UTC, monarch_dodra wrote:
>> struct RCArray(E) {
>>  E[] array;
>>  int* count;
>>  ...
>> }
>> auto x =  RCArray([E()]);
>> E* t = &x[0];
>
> But taking that address is unsafe to begin with. Do arguably, 
> this isn't that big of a problem.

Taking the address is only really unsafe (in a non-RC'd type) if 
you don't have a lifetime tracking system. As long as the 
lifetime of the address taker is shorter than the address of the 
takee, it's not inherently unsafe. Whether D will end up with 
such a system is a different question.

But I still think there's value in having a separate RCData type, 
because you can save one pointer per instance of RCArray. Right 
now, if you take a slice of an RCArray, your working array might 
not start at the same place as the reserved memory array. 
Therefore you need to keep a pointer to the reserved memory in 
addition to your active working array. If the counter and the 
pointer to the original memory are in the same place, one pointer 
will get you both.

I think the idea is worth exploring.

> Your first dual reference issue seems much more problematic, as 
> there are always cases the compiler can't catch.

How so? If all we're talking about is RC'd types, the compiler 
can catch everything. I think the greater concern is that the 
workarounds will take a toll in runtime performance. I'll try to 
illustrate:

void fun(ref RCStruct a, ref RCStruct b);

auto x = new RCStruct;
fun(x, x);

This wouldn't be safe. If fun() contained a line "a = new 
RCStruct;", b will point to deleted memory for the rest of the 
function. The normal way to protect this to make sure there's 
another reference:

auto y = x;
fun(x,x);

This is actually safe, because y bumps the reference counter to 2 
when initialized, which is enough to cover all possible 
reassignments of x. The compiler could do this automatically. It 
could detect that the parameter x aliases itself and create a 
temporary copy of x. But it would mean the runtime performance 
cost of the copy and postblit and destructor call. So D probably 
can't invest in that strategy, since the programmer should have a 
choice about it.

So it's not about it being impossible to deal with the safety 
problems here, just that the runtime cost is too high.

But there are some ways out. If the given type has no postblit, 
for example (or "opAddRef" for  classes), there's no reason to 
mark the operation unsafe, since you know it's not reference 
counted. Also, const parameters are safe and won't be affected.


More information about the Digitalmars-d mailing list