D structs weak identity and RAII

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jun 18 23:34:49 PDT 2017


On 06/18/2017 06:22 PM, Boris-Barboris wrote:

 > https://dpaste.dzfl.pl/d77c72198095
 >
 > 1). line 47 and 76 together mean, that there is basically no reliable
 > way to write uniqueptr method wich returns WeakPointer, registered by
 > the correct pointer in it's constructor. Or is there? Is usage of &this
 > in constructor (or in struct methods in general) fundamentally
 > unreliable in D?

It's unreliable because structs are value types in D, which means that 
they can be moved around freely. This is why self-referencing structs 
are illegal in D.

 > 2). postblit was never called when returning struct from function.

Rvalues are automatically moved and there is also RVO.

 > 3). Is there a way to reliably encapsulate all assignments?

I think so.

 > 4). Any suggested workarounds? I never tried it in C++, but, IIRC,
 > struct life cycle is much more consistent there ang gives the strict
 > control I desire.

Yes, C++ has a very well defined object lifecycle.

 > 5). If all this is a design choice, what is the reason behind it?

Some are design choices and some are bugs. For example, a fundamental 
bug has just been fixed: When a constructor threw, the destructors of 
already-constructed members were not being called. I think the fix is in 
git head but not released yet.

I can't claim expertise but here is a quick and dirty proof of concept 
that Vittorio Romeo and I had played with a few weeks ago:

import core.stdc.stdio;
import core.stdc.stdlib;
import std.algorithm;
import std.stdio;

shared byte b; // to prevent compiler optimizations

struct UniquePtr {
     void * p;

     this(void * p) {
         this.p = p;
         import core.atomic;
         core.atomic.atomicOp!"+="(b, 1);
     }

     ~this() {
         free(p);
     }

     @disable this(this);

     UniquePtr move() {
         void * old = p;
         p = null;
         return UniquePtr(old);
     }
}

void consumer(UniquePtr u) {
}

UniquePtr producer(int i) {
     auto u = UniquePtr(malloc(42));
     return i ? UniquePtr(malloc(56)) : u.move();
}

void main() {
     consumer(UniquePtr(malloc(2)));

     auto u = UniquePtr(malloc(5));
     consumer(u.move());

     auto u2 = producer(43);
}

Note how post-blit is disabled there. In addition to a moveFrom(), 
that's exactly what Atila Neves had to do in this automem library as well:

   https://github.com/atilaneves/automem

Ali



More information about the Digitalmars-d-learn mailing list