what exactly does cast(shared) and cast away shared do?

mw mingwu at gmail.com
Tue Jun 16 06:15:11 UTC 2020


I'm trying this program:

-----------------------------------------------------------------------------
class Foo {
   int attr;

   this() {
     writeln("Foo.ctor:", &attr);
   }
}

void threadInc(shared Foo foo) {
   writeln("threadInc:", &foo);
   writeln("threadInc:", &(foo.attr));
   Foo f = cast(Foo)foo;
   writeln("threadInc:", &f);
   foo.attr = 123;
}

void main() {
   Foo foo = new Foo();
   writeln("main:\t", &foo);
   writeln("main:\t", &(foo.attr));

   spawn(&threadInc, cast(shared)foo);  // cannot pass foo: Error: 
static assert:  "Aliases to mutable thread-local data not 
allowed." Have to cast to shared
   thread_joinAll();

   writeln("main:", foo.attr);
   writeln("main:\t", &foo);
   writeln("main:\t", &(foo.attr));

   shared sf1 = cast(shared)foo;
   shared sf2 = cast(shared)foo;
   writeln("sf1:\t", &sf1, "\t", &(sf1.attr));
   writeln("sf2:\t", &sf2, "\t", &(sf2.attr));

   foo.attr = 456;
   writeln("main:", foo.attr);
   writeln("main:", sf1.attr);
   writeln("main:", sf2.attr);
}
-----------------------------------------------------------------------------

here is the result:

-----------------------------------------------------------------------------
Foo.ctor:7FB83F4B0010              <- &attr is always the same
main:   7FFFD6D081F0               <- &foo
main:   7FB83F4B0010
threadInc:7FB83E1EFC08             <- cast(shared)foo
threadInc:7FB83F4B0010
threadInc:7FB83E1EFBF8             <- cast(Foo)foo, but != the 
original &foo
main:123
main:   7FFFD6D081F0               <- foo
main:   7FB83F4B0010
sf1:    7FFFD6D08200    7FB83F4B0010   <- each time 
cast(shared)foo will have a new addr
sf2:    7FFFD6D08208    7FB83F4B0010   <- but &(x.attr) is always 
the same
main:456
main:456
main:456
-----------------------------------------------------------------------------

In all the 3 cases, &(foo.attr) are the same; this is what I 
wanted, since the object is allocated on the heap.

But the memory address of the original foo, cast(shared) foo, and 
cast(Foo) foo are all different.

And for sf1, sf2, each time cast(shared)foo will have a new addr.

So every time cast(shared) / cast away shared will create a new 
wrapper to the original object, but all these wrappers' actual 
fields (the physical addr) stay the same?

What's the point of doing these wrappers every time?

Esp. for sf1, and sf2?  `shared` means it's globally *shared*, 
everywhere it's the same object, then why we have &(sf1) != 
&(sf2)?


What's the exact semantics of cast(shared) and cast away shared?


Thanks.



More information about the Digitalmars-d mailing list