[Dlang-study] [lifetime] Initial thoughts on lifetime management

Andrei Alexandrescu andrei at erdani.com
Wed Oct 28 12:20:51 PDT 2015


On 10/28/2015 02:00 PM, Timon Gehr wrote:
>> void bar() {
>>      C c = new C();
>>      [[auto __t = c; __t.refs += 2;]]
>>      foo(c, c);
>>      [[__t.refs -= 2;]]
>> }
>
> +=2 seems arbitrary. Only one new reference is generated.

I was thinking conservatively - add 1 for anything passed in, whether by 
value or reference.

Generally I'm very optimistic about conservative analyses - analyses 
that look at a function statically and conclude that the reference count 
can't go beyond e.g. 12 or whatever. Then upon object creation there's 
__t.refs+=12 and upon exit there's a __t-=12 and inside the function 
proper there's no other refcount bump.

Basic idea being +=1 or +=100 have the same cost, and refcount doesn't 
need to precisely reflect the number of references, only >=. We can 
exploit these facts.

(There are other analyses that compute conservative bounds, such as our 
well-known VRP or computing the stack frame size for a function.)

> Anyway, the solution is indeed to make it the responsibility of the
> caller to keep the borrowed object alive. I.e. when passing a non-scope
> reference to a scope argument, the reference count must be increased for
> the duration of the call. The benefit is that scope references can be
> duplicated arbitrarily without updating the reference count.
> This applies to globals just as well as to other cases.

Sounds interesting. So it looks like one additional hidden variable per 
reference created in a scope may be necessary in order to avoid 
complicated inc/dec for references.

> (I haven't read DIP74 though, so I might be misinterpreting your
> intentions.)

I'm glad you didn't because (a) it's better to have a fresh mind, (b) 
DIP74 has progressively integrated cases we hadn't thought of, and 
became a mess.


Andrei


More information about the Dlang-study mailing list