[Dlang-study] [lifetime] Few root decisions to take on RC classes

bitwise bitwise.pvt at gmail.com
Mon Nov 2 18:53:35 PST 2015


On Tuesday, 3 November 2015 at 00:36:35 UTC, Andrei Alexandrescu 
wrote:
> On 11/02/2015 06:28 PM, Martin Nowak wrote:
>> What if I want to use an existing (GC) class as ref counted, 
>> something
>> like core.thread.Thread?
>
> I suspect converting a GC class to an @rc class would require 
> at least changes wrt escaping addresses of members.
>
>> Tacking @rc on it would break some existing
>> code, but not doing it requires the GC.
>
> Probably that's the general case. But if a class has no public 
> data members and member functions that don't leak member 
> addresses, it stands to reason conversion could break no code.
>
>> Same goes for specifying an allocator to use with a ref 
>> counted class.
>
> I don't understand this part, could you please detail.
>
>> It seems like a much better idea to decide that when using the 
>> class as
>> opposed to when implementing the class.
>
> Such an approach would need to first define which subset of 
> classes work with both GC and RC. Do we agree on that? For 
> example, classes that escape addresses of data members work 
> safely only with GC. Same goes about classes that escape "this".
>
> For my money, I have long looked for a way to implement 
> reference counting outside of the class definition. I had my 
> mind modeled after the C++ approach, and it does seem like a 
> very sensible idea. Lately, however, I got disabused about the 
> notion because I figured the set of manipulations allowed to GC 
> classes largely surpasses the set of manipulations allowed to 
> RC classes.
>
> I am curious how you think you can define these two subsets.
>
>
> Andrei

Why not just do something like a C++ shared_ptr with compiler 
support?

If @rc was treated like a storage class, it could mean "this type 
is a compiler assisted shared_ptr". Any D type could then be @rc, 
including those that needed to escape an @rc aggregate. With 
compiler support, use of something like 'make_shared' would be 
implicit, avoiding the potential double allocation of a C++ 
shared_ptr. Also, taking the address or getting a ref of an 
aggregate member could implicitly yield an @rc of that type.

Example:

@rc class Foo
{
   int x;

   // error: invalid conversion from @rc(int) to int*
   // int* getNum() { return &x; }

   // ok
   @rc(int) getNum() { return &x; }
}

In the above example, taking the address of Foo::x would yield an 
@rc(int) which aliased the ref count and data pointers from the 
@rc(Foo), just like a C++ shared_ptr aliasing ctor, but hidden 
from the programmer.

    Bit


More information about the Dlang-study mailing list