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.

Reply via email to