www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 4419] New: __gshared static in class has no effect

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419

           Summary: __gshared static in class has no effect
           Product: D
           Version: D2
          Platform: x86
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: torhu yahoo.com


--- Comment #0 from torhu yahoo.com 2010-07-03 04:11:02 PDT ---
DMD 2.047.

Putting __gshared in front of static has no effect.  Putting it after works.

This example prints "0", instead of the expected "1":

---
import core.thread;
import std.stdio;

class A { __gshared static int x; }


void main()
{
    A.x = 1;
    Thread t = new Thread({ writeln(A.x); });
    t.start();
}
---

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 03 2010
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Trass3r <mrmocool gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mrmocool gmx.de
           Severity|normal                      |major


--- Comment #1 from Trass3r <mrmocool gmx.de> 2011-02-23 02:51:16 PST ---
This isn't restricted to classes:

__gshared static int a;
static __gshared int b;

 dmd -c -vtls foo.d
foo(1): a is thread local -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 23 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Trass3r <mrmocool gmx.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Platform|x86                         |All
         OS/Version|Windows                     |All


--- Comment #2 from Trass3r <mrmocool gmx.de> 2011-02-23 06:13:36 PST ---
Ok, part of the magic happens in StorageClassDeclaration::semantic() in
attrib.c (which btw duplicates setScope!):

StorageClass scstc = sc->stc;

/* These sets of storage classes are mutually exclusive,
 * so choose the innermost or most recent one.
 */
if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
    scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
    scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest |
STCgshared);
...
scstc |= stc;

In b's case sc->stc is 0, thus nothing gets truncated and scstc = stc, which is
ok cause stc correctly was set to STCstatic | STCgshared before.

In a's case however sc->stc == STCgshared, so it gets cut out by the second if
statement. Then scstc is set to stc which is equal to STCstatic.


So there are in fact 4 issues here:
1) Why is static and __gshared mutually exclusive, doesn't __gshared imply
static?
2) Why isn't shared handled in that list?
3) Why the difference regarding to the scopes? According to my debug view they
are perfectly identical except for the storage class.
4) Why the difference in stc?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 23 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419



--- Comment #3 from Trass3r <mrmocool gmx.de> 2011-02-23 06:50:26 PST ---
Ok 3 and 4 are caused by Parser::parseDeclDefs' layout.

If static comes first "case TOKstatic" is reached, TOKstatic is added and at
label Lstc2 TOKgshared is added. Then a single StorageClassDeclaration is
constructed with STCstatic|STCgshared.

If gshared comes first a chain of StorageClassDeclarations is constructed:
StorageClassDeclaration(gshared, StorageClassDeclaration(static, int a))

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 23 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Fawzi Mohamed <fawzi gmx.ch> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |fawzi gmx.ch


--- Comment #4 from Fawzi Mohamed <fawzi gmx.ch> 2012-10-04 15:11:55 PDT ---
I just fell in this bug, I find it *very* ugly, initially I though __gshared
was fully broken, and one had to use shared (that works).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 04 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Andrej Mitrovic <andrej.mitrovich gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich gmail.com


--- Comment #5 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2012-12-20
14:37:29 PST ---
 1) Why is static and __gshared mutually exclusive, doesn't __gshared imply
static? It implies the field is a property of the type, not the instance. It's *like* static, but static == TLS, __gshared == global. I think maybe the OP thought __gshared was a modifier you can apply to static, but it's not, __gshared can be (and should be) used alone. Both "static __gshared" and "__gshared static" should be rejected, because you can't ask the compiler "make this field thread-local *and* global, and make it a property of the type". It's either TSL or global, not both. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 20 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies gmail.com


--- Comment #6 from yebblies <yebblies gmail.com> 2013-07-28 15:28:04 EST ---
I agree that __gshared should imply static.  I was very surprised to find this
was not how it works.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jul 27 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Puneet Goel <puneet coverify.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |puneet coverify.org


--- Comment #7 from Puneet Goel <puneet coverify.org> 2013-08-24 07:37:52 PDT
---
(In reply to comment #5)
 1) Why is static and __gshared mutually exclusive, doesn't __gshared imply
static? It implies the field is a property of the type, not the instance. It's *like* static, but static == TLS, __gshared == global. I think maybe the OP thought __gshared was a modifier you can apply to static, but it's not, __gshared can be (and should be) used alone. Both "static __gshared" and "__gshared static" should be rejected, because you can't ask the compiler "make this field thread-local *and* global, and make it a property of the type". It's either TSL or global, not both.
But I see both "static __gshared" and "__gshared static" used in phobos as well as druntime. Many of this usages I believe should be buggy! See.... $ find . -type f -exec grep -nH -e "__gshared static" {} + ./phobos/std/parallelism.d:1039: __gshared static size_t nextInstanceIndex = 1; ./phobos/std/parallelism.d:3271: __gshared static TaskPool pool; ./druntime/src/core/thread.d:3862: __gshared static fp_t finalHandler = null; -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419


Rory <rjmcguire gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rjmcguire gmail.com


--- Comment #8 from Rory <rjmcguire gmail.com> 2013-09-13 03:34:04 PDT ---
(In reply to comment #6)
 I agree that __gshared should imply static.  I was very surprised to find this
 was not how it works.
There is no way that shared and static are the same. is __gshared so different from shared? sometimes I need to make a class member shared so that any thread can read/write to it, but I need the class to have multiple instances. The exact example is a class that contains a threadsafe queue which multiple threads wait for new tasks by reading and multiple threads add new tasks. I'd hate to have to always make these static. Whats interesting about dmd.2.063.2 is that the below makes a shared instance per class: class MyClass { shared chan!bool ready; this() { ready = makeChan!bool(1); } } BUT: class MyClass { shared chan!bool ready = makeChan!bool(1); } creates a static instance which is shared amoungst all classes and sub classes. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 13 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419



--- Comment #9 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-09-13
06:44:41 PDT ---
(In reply to comment #8)
 class MyClass {
     shared chan!bool ready = makeChan!bool(1);
 }
 
 creates a static instance which is shared among all classes and sub classes.
I can't reproduce this, can you paste what 'chan' is, or just paste the full example? E.g.: ----- class C { shared bool ready = false; static shared bool statReady = false; } void main() { auto a = new C; auto b = new C; a.ready = true; assert(b.ready == false); assert(&a.ready !is &b.ready); a.statReady = true; assert(b.statReady == true); assert(&a.statReady is &b.statReady); } ----- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 13 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419



--- Comment #10 from Rory <rjmcguire gmail.com> 2013-09-13 13:58:37 PDT ---
(In reply to comment #9)

 I can't reproduce this, can you paste what 'chan' is, or just paste the full
 example? E.g.:
 
Could you try this? class B { bool v;} class C { shared B ready = new shared B; static shared B statReady = new shared B; } void main() { auto a = new C; auto b = new C; a.ready.v = true; assert(b.ready.v == false); assert(&a.ready.v !is &b.ready.v); a.statReady.v = true; assert(b.statReady.v == true); assert(&a.statReady.v is &b.statReady.v); } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 13 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=4419



--- Comment #11 from Andrej Mitrovic <andrej.mitrovich gmail.com> 2013-09-13
14:01:21 PDT ---
(In reply to comment #10)
 (In reply to comment #9)
 
 I can't reproduce this, can you paste what 'chan' is, or just paste the full
 example? E.g.:
 
Could you try this? class B { bool v;} class C { shared B ready = new shared B; static shared B statReady = new shared B; } void main() { auto a = new C; auto b = new C; a.ready.v = true; assert(b.ready.v == false); assert(&a.ready.v !is &b.ready.v); a.statReady.v = true; assert(b.statReady.v == true); assert(&a.statReady.v is &b.statReady.v); }
This is a slightly different issue, it's the field initializer that is tricking you into thinking it's a new instance per class, but in fact that initializer is invoked at *compile-time*. Try this: ----- class B { bool v; } class C { this() { ready = new shared B; } shared B ready; static shared B statReady = new shared B; } void main() { auto a = new C; auto b = new C; a.ready.v = true; assert(b.ready.v == false); assert(&a.ready.v !is &b.ready.v); a.statReady.v = true; assert(b.statReady.v == true); assert(&a.statReady.v is &b.statReady.v); } ----- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Sep 13 2013