draft proposal for ref counting in D

Walter Bright newshound2 at digitalmars.com
Wed Oct 9 16:58:41 PDT 2013


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.

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.

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. 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).

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.

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...

-Steve


More information about the Digitalmars-d mailing list