Threads, shread and TLS
Steven Schveighoffer
schveiguy at yahoo.com
Fri Jan 7 07:03:22 PST 2011
On Fri, 07 Jan 2011 09:55:33 -0500, Adam Conner-Sax
<adam_conner_sax at yahoo.com> wrote:
> == Quote from Adam Conner-Sax (adam_conner_sax at yahoo.com)'s article
>> So, I thought I sort of understood "shared" and now I think I don't.
>> If I have a class:
>> class foo {
>> int x;
>> static int y;
>> shared static int z;
>> }
>> So x is one instance per class and is thread-local?
>> y is one instance per thread?
>> z is one instance per application, i.e., global?
>> If that's true (and I realize it might not be), and I want to
>> initialize these
>> variables in constructors, how does that work?
>> I think
>> class foo {
>> ...(as before)
>> this() { x = 2; } // ok
>> static this() { y = 3; } // is this called once per thread?
>> shared static this() { z = 3;} // also, okay, called before main
>> }
>> but I don't understand what happens with threads and the "static this"
>> constructor. How/when are the thread-local copies constructed? How do
>> you
>> initialize/construct the thread-local static data?
>> Thanks!
>> Adam
>
> Nevermind. Answered myself with the following:
>
> import core.thread;
> import std.c.stdio;
>
> class foo {
>
> int a;
> shared int b;
>
> static int x;
> shared static int y;
> shared static int[] arr1;
> shared static int[] arr2;
>
> this() { a = 1; b=10; }
> static this() { x=100; arr1 ~= x; }
> shared static this() { y=1000; arr2 ~= y; }
>
> static void A() { x++; y++; }
> void B() { a++; b++; }
> void report() {
> printf("a=%i; b=%i; x=%i; y=%i; arr1.length=%i;
> arr2.length=%i\n",a,b,x,y,arr1.length, arr2.length);
> }
> }
>
> void main()
> {
> auto f = new foo();
> void call_foo_functions() { f.A(); f.B(); f.report(); }
> auto tg = new ThreadGroup();
> foreach (k; 0..3) {
> auto t = new Thread(&call_foo_functions);
> tg.add(t);
> t.start();
> }
> tg.joinAll();
> printf("back in main: ");
> f.report();
> }
>
> which output:
>
> a=2; b=11; x=101; y=1001; arr1.length=2; arr2.length=1
> a=3; b=12; x=101; y=1002; arr1.length=2; arr2.length=1
> a=4; b=13; x=101; y=1003; arr1.length=3; arr2.length=1
> back in main: a=4; b=13; x=100; y=1003; arr1.length=3; arr2.length=1
>
>
> which all makes sense (to me) except a. Why is a acting global? Is it
> since it
> isn't static so it belongs to the class and there is only one copy of
> the class?
> Then what makes a and b different?
OK, so here is what is happening :)
call_foo_functions is a delegate, which means it has a frame pointer to
the main function. So all three threads' f is the *same* f (the one
defined in main()).
I would suggest that you move call_foo_functions outside main, and
instantiate an additional f *inside* the function. This would be more
correct.
Incidentally, it appears that this allows untagged sharing (i.e. sharing
data that isn't tagged with shared) I wonder if this issue has been
reported before? Sean?
>
> Also, though maybe it's obvious to everybody else, I think the docs
> should explain
> someplace that "static this()" gets called once *per thread*. Maybe I
> just missed it.
>
Yes, the documentation is out of date. Could you file a bugzilla report
on this?
-Steve
More information about the Digitalmars-d-learn
mailing list