Skip to content

Conversation

idanarye
Copy link
Contributor

http://d.puremagic.com/issues/show_bug.cgi?id=10165

The new std.typecons.Shared allows the declaration of thread-local
shared variables:

    static class Foo
    {
        static shared(Foo) a;
        static Shared!Foo b;
    }

    //Initialize both a and b in another thread:
    auto thread = new core.thread.Thread({
            Foo.a = new shared(Foo)();
            Foo.b = new shared(Foo)();
            });
    thread.start();
    thread.join();

    //a is static shared, so there is one Foo.a for all threads.
    assert(Foo.a !is null);
    //b is just static, so this thread has a different Foo.a.
    assert(Foo.b is null);

This is a problem I encountered while designing the shared version of the low lock singleton for my std.idioms library - there is some forum discussion about it here: http://forum.dlang.org/thread/fofbrlqruxbevnxchxdp@forum.dlang.org?page=5#post-knnqp6:242l7h:241:40digitalmars.com

http://d.puremagic.com/issues/show_bug.cgi?id=10165

The new `std.typecons.Shared` allows the declaration of thread-local
shared variables:

```D
    static class Foo
    {
        static shared(Foo) a;
        static Shared!Foo b;
    }

    //Initialize both a and b in another thread:
    auto thread = new core.thread.Thread({
            Foo.a = new shared(Foo)();
            Foo.b = new shared(Foo)();
            });
    thread.start();
    thread.join();

    //a is static shared, so there is one Foo.a for all threads.
    assert(Foo.a !is null);
    //b is just static, so this thread has a different Foo.a.
    assert(Foo.b is null);
```
@ghost
Copy link

ghost commented Oct 24, 2013

This seems like a language issue. @9rnsr what are your thoughts about this?

@ghost
Copy link

ghost commented Feb 15, 2014

@andralex @yebblies @MartinNowak Concurrency guys make your move here.

@MartinNowak
Copy link
Member

A thread-local variable is head unshared.
For value types (e.g. int, float) this means they are not shared,
for reference types only the tails is shared (e.g. shared(void)*, shared(int)[]),
for classes you run into a syntax problem already know from const.
dlang/dmd#3

So what you're trying to get is Rebindable for shared instead of const.
I would rather go with HeadUnshared instead of Shared and only make it applicable for classes.
http://vibed.org/temp/dlang.org/library/std/typecons/Rebindable.html

@yebblies
Copy link
Contributor

We need to fix that damn tail-const-class problem.

@ghost
Copy link

ghost commented Feb 16, 2014

We need to fix that damn tail-const-class problem.

AIUI this would also help porting D1 or (porting/wrapping) C++ code to D2, no?

@yebblies
Copy link
Contributor

AIUI this would also help porting D1 or (porting/wrapping) C++ code to D2, no?

I sure wouldn't want to port any C++ code that uses const heavily to D at the moment.

@ghost
Copy link

ghost commented Feb 16, 2014

I sure wouldn't want to port any C++ code that uses const heavily to D at the moment.

You're lucky DMD-FE barely uses it. :P

@yebblies
Copy link
Contributor

You're lucky DMD-FE barely uses it. :P

I would rather have removed that than macros, although it might have been a harder sell.

@mihails-strasuns
Copy link

This needs to be implemented as a general solution - as mentioned by @MartinNowak there are too many similarities to Rebindable. Good common name can be tricky though. RefUnqual? (RefUnqual!(shared Foo) , RefUnqual!(const Foo))

Unless @idanarye wants to do anything with it I am going to close it as soon as get my hands to replacement PR.

@idanarye
Copy link
Contributor Author

@Dicebot Rebindable seems much more complex than Shared to me - I don't really see how a general type can implement them both...

@mihails-strasuns
Copy link

With tiny tweak to static if condition this works as desired:

static class Foo
{
    static shared(Foo) a;
    static Rebindable!(shared Foo) b;
}

void main()
{
    auto thread = new core.thread.Thread({
            Foo.a = new shared(Foo)();
            Foo.b = new shared(Foo)();
   });
    thread.start();
    thread.join();

    assert(Foo.a !is null);
    assert(Foo.b is null);
}

Only problem is that current name (Rebindable) is too specific and backwards-compatibility demands exactly same semantics. I propose adding new UnqualRef utility in the same module which will strip all qualifiers and alias current Rebindable as special case for stripping only const/immutable.

@mihails-strasuns
Copy link

Have added competing PR.

@idanarye
Copy link
Contributor Author

I'm closing this PR in favor of #2342

@idanarye idanarye closed this Jul 23, 2014
quickfur pushed a commit that referenced this pull request Sep 4, 2014
Fix issue 10165 (rework of PR #1302)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants