www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - shared attribute

reply "japplegame" <japplegame gmail.com> writes:
Does shared attribute automatic synchronization or should I do it 
manually?
May 13 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, May 13, 2012 11:24:58 japplegame wrote:
 Does shared attribute automatic synchronization or should I do it
 manually?

shared does not automatically synchronize anything. It just means that the variable is shared across threads rather than being thread-local, and the compiler takes that into account with whatever optimizations and code generation it does. It does nothing to protect against multiple threads accessing it simultaneously. - Jonathan M Davis
May 13 2012
prev sibling next sibling parent "japplegame" <japplegame gmail.com> writes:
Thanks.
Another question.
This doesn't compile:
shared char[] s = "shared text".dup;

cannot implicitly convert expression ("shared text") of type 
char[] to shared(char[])

shared char[] s = cast(shared)"shared text".dup;

May 13 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, May 13, 2012 13:36:31 japplegame wrote:
 Thanks.
 Another question.
 
 This doesn't compile:
shared char[] s = "shared text".dup;

with error:
cannot implicitly convert expression ("shared text") of type
char[] to shared(char[])

Why do I need to write this?
shared char[] s = cast(shared)"shared text".dup;

What is the meaning of this casting?

"shared text".dup is char[]. Note there is no shared, so it's thread-local. If you cast it to shared auto s = cast(shared char[])"shared text".dup; or shared char[] s = cast(shared)"shared text".dup; that makes the compiler treat that value as shared. As you just created the value, that's fine, but it's something that you need to be very careful of if there are other references to the same data, since the compiler will treat anything not marked as shared as thread-local. So, if you have one reference which is non-shared and one which is shared pointing to the same data, then you'll likely to end up with bugs in the code with the non-shared reference (since the compiler will make optimizations based on the fact that it's not shared). You're forced to do the cast here, because you're dealing with a string literal rather than a type with a constructor. If it had a constructor, you'd do something more like shared s = new shared(MyType)(args); and no cast would be necessary. - Jonathan M Davis
May 13 2012
prev sibling next sibling parent "japplegame" <japplegame gmail.com> writes:
Very intresting. Next question. :)
Lets consider this example.
import core.thread;
import std.stdio;

shared char[] s;
char[] l = "shared text".dup;

void main() {
  Thread worker = new Thread(&workerFunc);
  worker.start();
  Thread.sleep(dur!"seconds"(5)); // after this point worker 
 thread and its
                                  // local storage most likely 
 destroyed
  s[2] = 'd';                     // undefined behaviour?
}

void workerFunc() {
   s = cast(shared)l;
}

May 13 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, May 13, 2012 14:35:14 japplegame wrote:
 Very intresting. Next question. :)
 Lets consider this example.
 
import core.thread;
import std.stdio;

shared char[] s;
char[] l = "shared text".dup;

void main() {

  Thread worker = new Thread(&workerFunc);
  worker.start();
  Thread.sleep(dur!"seconds"(5)); // after this point worker
 
 thread and its
 
                                  // local storage most likely
 
 destroyed
 
  s[2] = 'd';                     // undefined behaviour?

}

void workerFunc() {

   s = cast(shared)l;

}


I actually don't know. Because you had to cast to shared, it might be undefined, but then again, the compiler might be smart enough to move it into non-thread local storage at that point. I don't know exactly what it does. If it had been constructed as shared in the first place (which you can't do with a string, unfortunately), it wouldn't be an issue at all, but it might be in this case. However, while I know the basics of shared, I'm not familiar with all of the nitty gritty details, so I can't really answer the question well. I'd suggest reading the concurrency chapter from TDPL (The D Programming Language by Andrei Alexandrescu) if you want all of the concurrency stuff explained. It may or may not answer your question (it's been a while since I read it). But unlike most of TDPL, that chapter is available for free online in case you don't have the book: http://www.informit.com/articles/article.aspx?p=1609144 The recommended way to deal with concurrency in D is to avoid shared and use message passing with std.concurrency (which is what I normally do). So, if you can do that in your program rather than using shared, that's recommended (though shared, synchronized, and mutexes are definitely there if you _do_ need them). - Jonathan M Davis
May 13 2012
prev sibling parent "japplegame" <japplegame gmail.com> writes:
Thank you very much.
I already readed this excellent article.
Unfortunately, sometimes we need things that should be global and
shared between threads.
As far as I understand it is desirable to avoid casting to/from
shared.
It will be better to use something like this
shared char[] s;
shared static this() {
  s ~= "shared text";
}

shared char[] s = cast(shared)"shared".dup;

May 13 2012