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