On Fri, 18 Apr 2014 01:53:00 -0400, Walter Bright <newshou...@digitalmars.com> wrote:

On 4/17/2014 6:58 PM, Michel Fortin wrote:
Auto-nulling weak references are perfectly memory-safe. In Objective-C you use the __weak pointer modifier for that. If you don't want it to be auto-nulling,
use __unsafe_unretained instead to get a raw pointer. In general, seeing
__unsafe_unretained in the code is a red flag however. You'd better know what
you're doing.

If you could transpose the concept to D, __weak would be allowed in @safe functions while __unsafe_unretained would not. And thus memory-safety is preserved.

I recall our email discussion about implementing ARC in D that we couldn't even avoid an inc/dec for the 'this' when calling member functions. So I don't see how inc/dec can be elided in sufficient numbers to make ARC performant and unbloated.

The important thing to recognize is that it's the *caller* that increments/decrements. This means you can elide calls to an object where you already have a guarantee of its reference count being high enough.

I looked up the example you referred to, it was this:

class R : RefCounted
{
   int _x;
   int readx() { return _x; }
}
int main()
{
   R r = new R;
   return r.readx();
}
According to 12. there is no refcounting going on when calling or executing readx. Ok, now what happens here:
class R : RefCounted
{
   int _x;
   int readx(C c)
   {
       c.r = null; // "standard" rc deletes r here
       return _x;  // reads garbage
   }
}
class C
{
   R r;
}
int main()
{
   C c = new C;
   c.r = new R;
   return c.r.readx(c);
}
This reads garbage or crashes if there is no reference counting going on when calling readx.

So essentially, main needs to increment c.r's ref count. But not c's, because it already knows that it owns one of c's reference counts. R.readx does NOT need to increment its own reference count.

I think the distinction is important.

Also, consider if R is a final class, it can inline readx and can possibly defer incrementing the ref count for later, or cache _x before setting c.r to null (probably the better option).

Opportunities for elision are not as hopeless as you make it sound. The compiler has a lot of information.

The rules should be:

1. when compiling a function, you can assume parameters have at least one reference count increment that will not go away. 2. When passing an object into a function, ensure #1 is true for that function.

Given D's type system of knowing when variables are shared (and if we implement thread-local destruction of unshared data), we have a lot more power even than Objective-C to make better decisions on ref counting.

Of course, you can always *manually* elide these things, but then if you make a mistake, then you've got a leak and memory corruption.

Manual eliding should be reserved for extreme optimization cases. It's similar to cast. Apple considers it dangerous enough to statically disallow it for ARC code.

-Steve

Reply via email to