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