www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Inconsistent behavior shared struct vs non-shared storage - bug?

reply apz28 <home home.com> writes:
import std.stdio;

enum sharedit = false;

__gshared int counter = 0;

class C
{
}

     struct S
     {
         C c;
         this(C c)
         {
             counter++; writeln("this(): ", counter);
             this.c = c is null ? new C() : c;
         }

         ~this()
         {
             counter--; writeln("~this(): ", counter);
         }

         int foo()
         {
             writeln("foo(): ", counter);
             return 1;
         }
     }

static if (sharedit) shared S s;
else __gshared S s;

     shared static this()
     {
         writeln("shared static this(1): ", counter);
         static if (sharedit) s = cast(shared)S(null);
         else s = S(null);
         writeln("shared static this(2): ", counter);
     }

     void main()
     {
         writeln("main(1): ", counter);
         static if (sharedit) auto i = (cast()s).foo();
         else auto i = s.foo();
         writeln("main(2): ", counter);
     }


/* sharedit = true
shared static this(1): 0
this(): 1
~this(): 0
shared static this(2): 0
main(1): 0
foo(): 0
main(2): 0
*/

/* sharedit = false
shared static this(1): 0
this(): 1
shared static this(2): 1
main(1): 1
foo(): 1
main(2): 1
*/
Jun 02
parent Iain Buclaw <ibuclaw gdcproject.org> writes:
On Wednesday, 2 June 2021 at 12:25:54 UTC, apz28 wrote:
     struct S
     {
         C c;
         this(C c)
         {
             counter++; writeln("this(): ", counter);
             this.c = c is null ? new C() : c;
         }
I suspect this is a topic better suited to d.learn, but you are missing a shared constructor. ``` shared this(shared C c) { counter++; writeln("this(): ", counter); this.c = c is null ? new shared C() : c; } ```
     shared static this()
     {
         writeln("shared static this(1): ", counter);
         static if (sharedit) s = cast(shared)S(null);
         else s = S(null);
         writeln("shared static this(2): ", counter);
     }
The `sharedit` path constructs a non-shared object, which you cast to a shared one. This causes a copy to occur, so what you're seeing is the destruction of the temporary. Instead, construct a shared object. ``` static if (sharedit) s = shared(S)(null); else s = S(null); ```
Jun 02