Issue 10165 - No syntax to create thread-local shared variables
Summary: No syntax to create thread-local shared variables
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2013-05-24 14:22 UTC by IdanArye
Modified: 2014-09-04 18:47 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description IdanArye 2013-05-24 14:22:39 UTC
Writing

    class Foo
    {
        shared Foo a;
        static Foo b;
        static shared Foo c;
    }

`a` is an instance-local shared reference. `b` is a thread-local not-shared reference. You would expect that `c` would be thread-local shared reference - but instead it's a process-global shared reference.

I do not suggest changing the behaviour of `static shared` - it is the syntax for process-global shared variables by design, and changing it will break too much code. But we do need a way to create thread-local shared variables.

I've implemented a library solution, but I believe this problem requires a compiler solution that's why the component field is "dmd".
Comment 1 Steven Schveighoffer 2013-05-24 14:30:04 UTC
I'm almost positive this works:

static shared(Foo) a;

That is, if shared is interpreted as a storage class, it puts the variable in global storage, not thread local.  But shared as a type constructor just affects the type.

Don't have the patience to test, so I'll leave the bug open :)
Comment 2 IdanArye 2013-05-24 14:43:55 UTC
Here is the pull request: https://github.com/D-Programming-Language/phobos/pull/1302

@Steven Schveighoffer: It doesn't work - `static shared(T)` does the same as `static shared T`.

I assume the proper solution would be to fix this, but I leave the pull request open anyways. Like I said - there should be a compiler solution - but we don't know how many people use the `static shared(T)` syntax with the intention of declaring a process-global variable, and we can't show a warning message when this syntax is used wrongly - so the dmd solution requires some serious debate. In the meanwhile, the Phobos solution doesn't break anything, and it took me 20 minutes: 1 for the implementation, 2 for the unit test, and the rest for all the "paperwork"(=sending this bug and the pull request) - so I planned from the beginning to send it and let the dev team decide if they want to use my Phobos solution or to fix it in dmd.
Comment 3 bearophile_hugs 2013-05-24 15:22:55 UTC
(In reply to comment #2)

> and let the dev team decide if they want to use my Phobos
> solution or to fix it in dmd.

Where possible in D we prefer to fix the language to help all future D programmer.
Comment 4 Walter Bright 2013-05-24 15:42:00 UTC
(In reply to comment #0)
>  But we do need a way to create thread-local shared variables.

Why? What is the motivating example?
Comment 5 IdanArye 2013-05-24 16:22:30 UTC
(In reply to comment #4)
> (In reply to comment #0)
> >  But we do need a way to create thread-local shared variables.
> 
> Why? What is the motivating example?

I'm implementing the low lock singleton - http://forum.dlang.org/thread/pelhvaxwjzhehdjtpsav@forum.dlang.org - as part of my `std.idioms` library - http://forum.dlang.org/thread/fofbrlqruxbevnxchxdp@forum.dlang.org - in both `shared` and `__gshared` versions(I also have a thread-local(=`static`) version, but it doesn't use the low lock implementation)

A small optimization in the implementation is instead of using a thread-local boolean indicator to determine if the singleton has been initialized yet, to save a thread-local reference to the actual instance object. That way, instead of accessing the memory twice(once to check the indicator and once to fetch the object) we only need to access it once.

Now, doing it in the `__gshared` version was straight-forward, but the `shared` version posed a problem - the need to have a thread-local reference to a shared object - hence this bug report and pull request.
Comment 6 Walter Bright 2013-05-24 19:35:18 UTC
You can have a thread-local reference to a shared object:

    static shared(T)* p;

p is thread local, and it points to a shared instance of T.
Comment 7 Dmitry Olshansky 2013-05-24 22:32:09 UTC
(In reply to comment #6)
> You can have a thread-local reference to a shared object:
> 
>     static shared(T)* p;
> 
> p is thread local, and it points to a shared instance of T.

The bug report is about classes. With T* that would be double indirection.
Comment 8 github-bugzilla 2014-09-04 18:47:00 UTC
Commits pushed to master at https://github.com/D-Programming-Language/phobos

https://github.com/D-Programming-Language/phobos/commit/4924d9ad240ef3b7ae4a099bad8b6e928e697069
Fix issue 10165 (rework of PR #1302)

http://issues.dlang.org/show_bug.cgi?id=10165
Issue 10165: No syntax to create thread-local shared variables

Adds `UnqualRef` templated alias/struct that is similar to Rebindable but
strips away all qualifiers completely (including shared)

https://github.com/D-Programming-Language/phobos/commit/3dda37428fe49ce76e5e8a6aa120054f836a1024
Merge pull request #2342 from Dicebot/ref-unqual

Fix issue 10165 (rework of PR #1302)