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