draft proposal for ref counting in D

Walter Bright newshound2 at digitalmars.com
Wed Oct 9 16:59:37 PDT 2013


On 6/25/2013 1:19 PM, Steven Schveighoffer wrote:
 > Looks like a good start.
 >
 > A few things:
 >
 > 1. Proposal point 3, you need to AddRef first, THEN Release the original. 
Reason being, you could be assigning a reference the same value as before. In 
this case, if you decrement *first*, you will decrement the reference, which 
might reduce it to 0, and free the object before you increment.  In most cases, 
the AddRef and Release are elided, so it's not bad if you do this.

Yeah, I got that backwards, and I should know better.

 >
 > I wonder if it's not a good idea to have a RefAssign function that takes two 
RC objects and does a check to see if they are the same before doing AddRef and 
Release to help with this issue. Calls where the compiler can prove they are the 
same value can be elided.

I'd like to see how far we get with just AddRef/Release first, and getting the 
semantics of them right first.

 >
 > 2. AddRef and Release should be treated not as function calls, but as 
callables. That is, if for some reason AddRef and Release should be aliases, 
this does not detract from the solution.

Yes, just like the names for Ranges are used.

 >   Only requirement should be that they cannot be UFCS, as that doesn't make 
any sense (one cannot add reference counting after the fact to an object).

That would be covered by disallowing explicit calls to AddRef/Release in @safe code.

 >
 > I'm thinking of the Objective-C objects, whose functions are "release" and 
"retain". It would be good to use the names Objective-C coders are used to.

AddRef/Release are the COM names. It's trivial to have one wrap the other. I 
picked AddRef/Release because I'm familiar with their semantics, and am not with 
O-C.


 >
 > 3. Objective-C ARC uses a mechanism called auto-release pools that help cut 
down on the release/retain calls. It works like this:
 >
 > @autoreleasepool {  // create a new pool
 >       NSString *str = [NSString stringWithFormat:@"an int: %d", 1];
 >       @autoreleasepool { // create a new pool on the "pool stack"
 >             NSDate *date = [NSDate date];
 >             {
 >                 NSDate *date2 = [NSDate date];
 >             }
 >       } // auto-release date and date2
 > } // auto-release str
 >
 > In this way, it's not the pointer going out of scope that releases the 
object, it's the release pool going out of scope that releases the object. These 
release pools themselves are simply RC objects that call release on all their 
objects (in fact, prior to the @autoreleasepool directive, you had to manually 
create and destroy these pools).
 >
 > The benefit of this model is that basically, inside a pool, you can move 
around auto-released objects at will, pass them into functions, return them from 
functions, etc, without having to retain or release them for each assignment. 
It's kind of like a mini-GC.
 >
 > It works by convention, that any function that returns a RC object:
 >
 > if it's called 'new...' or 'init...' or 'alloc...' or 'copy...', then the 
object is assumed returned with it's retain count incremented on behalf of the 
calling scope. This means, if you assign it to a member variable, for instance, 
you do not have to retain the object again, and if it goes out of scope, you 
must call release on it.
 >
 > All other functions return 'auto-released' objects, or objects which have 
queued in the latest auto release pool. The compiler knows this and can elide 
more of the releases and retains.
 >
 > Would this be a mechanism that's worth putting in? I think it goes really 
well with something like TempAlloc.  I don't think we should use convention, 
though...

I agree with not relying on convention. But also reserving the new*, init*, 
alloc* and copy* namespaces seems excessive for D.

As for autoreleasepool, it is relying on a convention that its fields are not 
leaking. I don't see how we can enforce this.



More information about the Digitalmars-d mailing list