Thread overview
[Issue 17543] __gshared block modifier is ignored by static variables
Jun 24, 2017
ZombineDev
Jun 24, 2017
ZombineDev
Jun 24, 2017
Robert Luger
Jun 24, 2017
ZombineDev
Jun 24, 2017
ZombineDev
June 24, 2017
https://issues.dlang.org/show_bug.cgi?id=17543

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |petar.p.kirov@gmail.com

--- Comment #1 from ZombineDev <petar.p.kirov@gmail.com> ---
All attributes (e.g. public/private, pure/nothrow/@safe/@nogc, const/shared, final, __gshared,  and so on) are applied only to the scope they are declared in. As soon as you open a new scope they are effectively reset.

--
June 24, 2017
https://issues.dlang.org/show_bug.cgi?id=17543

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
           Hardware|x86                         |All
         Resolution|---                         |INVALID
                 OS|Windows                     |All

--- Comment #2 from ZombineDev <petar.p.kirov@gmail.com> ---
I'll close this bug as there's nothing specific to __gshared, but of course you're free to open a discussion on the newsgroup and to propose a way to control this. I have an idea for a DIP (D improvement proposal) on that matter, but no promises when I'll have enough time to sit down, write it down and submit it.

--
June 24, 2017
https://issues.dlang.org/show_bug.cgi?id=17543

--- Comment #3 from Robert Luger <weltensturm@gmail.com> ---
This works though:


import std.stdio, std.parallelism;


__gshared:


auto return_gshared(){

    class Test {
        bool set;
    }

    return new Test();

}


void main(){
    auto obj = return_gshared();
    auto t = { obj.set = true; }.task;
    t.executeInNewThread;
    t.spinForce;
    writeln(obj.set);
}

--
June 24, 2017
https://issues.dlang.org/show_bug.cgi?id=17543

--- Comment #4 from ZombineDev <petar.p.kirov@gmail.com> ---
(In reply to Robert Luger from comment #3)
> This works though:
> 
> 
> import std.stdio, std.parallelism;
> 
> 
> __gshared:
> 
> 
> auto return_gshared(){
> 
> 	class Test {
> 		bool set;
> 	}
> 
> 	return new Test();
> 
> }
> 
> 
> void main(){
> 	auto obj = return_gshared();
> 	auto t = { obj.set = true; }.task;
> 	t.executeInNewThread;
> 	t.spinForce;
> 	writeln(obj.set);
> }

__gshared has no effect in the program above (e.g. commenting it out doesn't
change the result). That's because the variable 'obj' of type 'Test' is shared
by both the main thread and the thread on which the task is executed.
One simple test to verify if a class/struct member is effectively 'static'
(i.e. shared by all instances of the current thread, or all threads (if it's
declared as either '__gshared' or 'static shared') is to check if:
* It has the 'offsetof' property, or
* If it can be accessed with the 'Type.staticMember' sytnax
(which is what I think effectively
http://dlang.org/phobos/std_traits#hasStaticMembery does)

__gshared:

auto return_gshared(){

    class Test {
        bool set;
    }

    pragma (msg, __traits(compiles, { size_t offset = Test.set.offsetof; }));
// true
    pragma (msg, Test.set.offsetof); // 16LU
    pragma (msg, __traits(compiles, { auto copyOfStaticVariable = Test.set;
})); // false

    return new Test();
}

--
June 24, 2017
https://issues.dlang.org/show_bug.cgi?id=17543

--- Comment #5 from ZombineDev <petar.p.kirov@gmail.com> ---
Just a tip: it's useful to encode such assumptions about how your code works by using 'static assert'. For example:

class Test
{
    int instanceMember;
    __gshared int globalGSharedMember;
    static int threadLocalStaticMember;
    static int globalSharedMember;
}

import std.traits : hasStaticMember;
static assert (!hasStaticMember!(Test, "instanceMember"));
static assert ( hasStaticMember!(Test, "globalGSharedMember"));
static assert ( hasStaticMember!(Test, "threadLocalStaticMember"));
static assert ( hasStaticMember!(Test, "globalSharedMember"));

--