RCArray is unsafe

Zach the Mystic via Digitalmars-d digitalmars-d at puremagic.com
Wed Mar 4 09:13:12 PST 2015


On Wednesday, 4 March 2015 at 08:13:33 UTC, deadalnix wrote:
> On Wednesday, 4 March 2015 at 03:46:36 UTC, Zach the Mystic 
> wrote:
>> That's fine. I like DIP25. It's a start towards stronger 
>> safety guarantees. While I'm pretty sure the runtime costs of 
>> my proposal are lower than yours, they do require compiler 
>> hacking, which means they can wait.
>
> I don't think that it is fine.
>
> At this point we need to :
>  - Not free anything as long as something is alive.
>  - Can't recycle memory.
>  - Keep track of allocated chunk to be able to free them (ie 
> implementing malloc on top of malloc).
>
> It means that RC is attached to an ever growing arena. Code 
> that would manipulate RCArray and append to it on a regular 
> manner must expect some impressive memory consumption.
>
> Even if we manage to do this in phobos (I'm sure we can) it is 
> pretty much guaranteed at this point that noone else will, at 
> least safely. The benefit is reduced because of the bookeeping 
> that need to be done for memory to be freed in addition to 
> reference count themselves.
>
> The #1 argument for DIP25 compared to alternative proposal was 
> its simplicity. I assume at this point that we have empirical 
> evidence that this is NOT the case.

To me, DIP25 is just the first step towards an ownership system. 
The only language additions you need to it are "out!" parameters, 
to track escapes to other parameters, "static" parameters 
(previously called "noscope"), to say that the parameter won't be 
copied to a global, and one more function attribute (for which I 
can reuse "noscope" as @noscope) which says the return value will 
nto be allocated on the heap. All of these will be rare, as they 
aim to target the exceptional cases rather than the norms 
("scope" would be the norm. Hence "@noscope" to target the rare 
cases):

Examples:

T* fun(return T* a, T* b, T**c);

This signature would indicate complete ownership transferred from 
`a` to the return value, since only `a` can be returned (see why 
below)

T* gun(return out!b T* a, T** b);

`a` is declared to be copied both to the return value and to `b`. 
Therefore it is not owned. (If you're following my previous 
definition of `out!` in DIP71, you'll notice I moved `out!` to 
the source parameter rather than the target, but the point is the 
same.)

T* hun(return T* a) @noscope {
   if(something)
     return a;
   else return new T;
}

Again, no ownership. If you *might* return a heap or global, the 
function must be marked @noscope (Again I've readapted the word 
to a new meaning from dIP71. I'm using `static` now for 
`noscope's original meaning.)

Another example:

T* jun(return static T* a) {
   static T* t;
   t = a;
   return a;
}

Again, no ownership, because of the `static` parameter attribute. 
In a previous post, you suggested that such an attribute was 
unnecessary, but an ownership system would require that a given 
parameter `a` which was returned, not also be copied to a global 
at the same time. So `static` tells the compiler this, and thus 
cancels ownership.

My point is that DIP25's `return` parameters are the beginning of 
an ownership system. An option to specify that the function 
*will* return a given `return` parameter as opposed to *might* 
return it is the only thing needed. Hence the additions named 
above. (Also, `pure` functions will need no `static` parameter 
attributes, and functions both `pure` and `@nogc` will not need )

With the exception of some minor cosmetic changes, all this is 
in, or at least hinted at, in my previously posted Reference 
Safety System:

http://forum.dlang.org/post/offurllmuxjewizxedab@forum.dlang.org

The only thing which bears reiterating is that with better 
attribute inference, the whole system becomes invisible for most 
uses.


More information about the Digitalmars-d mailing list