what exactly does cast(shared) and cast away shared do?
Simen Kjærås
simen.kjaras at gmail.com
Tue Jun 16 06:53:22 UTC 2020
On Tuesday, 16 June 2020 at 06:15:11 UTC, mw wrote:
> 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?
The only thing cast(shared) does is tell the type system 'this
object is shared'. The reason you're getting different addresses
is you're taking the address of the reference on the stack. As
you've noticed, &foo.attr, &(sf1.attr), &(sf2.attr) is exactly
the same, so the actual instances are the same.
So in D, unlike C++, you can't really refer to a class instance
directly - you always have a reference to the instance instead.
When you have 'Foo instance = new Foo();', 'instance' is, behind
the scenes, a pointer, for instance 7FB83F4B0000. When you
further add 'Foo instance2 = instance;', they both refer to the
same object. However, 'instance' and 'instance2' are themselves
separate variables, placed on the stack, and they will have their
own addresses, which is what you get with &instance and
&instance2. If you look at the addresses you get for &foo vs
&(foo.attr), you will notice they are significantly different,
which you would not expect for a pointer to the instance vs a
pointer to a field inside that instance, unless the instance was
humongous.
Since I've told you class references are pointers behind the
scenes, you can print their values by casting them to to some
kind of pointer. Try replacing &foo in the code with
cast(int*)foo, and you'll see they all point to the same memory
(8 or 16 bytes before the address of attr, since class instances
have some hidden fields - vtable and monitor).
--
Simen
More information about the Digitalmars-d
mailing list