http://d.puremagic.com/issues/show_bug.cgi?id=10108
Igor Stepanov <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #8 from Igor Stepanov <[email protected]> 2013-05-17 13:57:50 PDT --- (In reply to comment #7) > Simplified example without __gshared: > > import core.thread; > > int[] arr = [1,2,3]; > > void main( ) { > int* p = arr.ptr; > auto thr = new Thread({assert(arr.ptr == p);}); // Should have failed. > thr.start(); > thr.join(); > } In other words implicit "thread local" modifier is not transitive. Yes, all threads have a local copy of "arr symbol" and &arr differs in different threads. But all of this "local" symbols points to single array object. The problem lies deeper than it seems. struct Foo { int[] arr; } Foo[] getFooArr() { Foo[] ret; foreach(i; 1 .. 10) { Foo cur; foreach(j; 1 .. 5) { cur.arr ~= j; } ret ~= cur; } return ret; } Foo[] arr = getFooArr(); Now foo points to the arr, each members of it points to array literal. And if we want to create Foo[] is true TLS object, we must to set, that 1. arr must point to tls object (arr.ptr must be thread_tls_start+arr_tls_offset) 2. for each i: arr[i].arr must point to tls object. In other words If compiler see ptr dereference expression (with * or []) it must know, is this ptr is TLS. If it is TLS compiler must add to it value thread_tls_start, otherwise - use it value as is. This functional can be provided, if we declare transitive threadlocal storage class (like shared) and implement special reference behaviour. (e.g. dereference, casting and other.) for example: theradlocal int[][] tls = [[1,2],[3,4],[5,6]]; int* getNthMthElemPointer(theradlocal int[][] a, int n, int m) { return &ptr[n][m]; //implicit cast to non-tls pointer. returned value points to elem it function caller thread } void main() { int* p1 = getNthMthElemPointer(tls, 1, 1); theradlocal int* p2 = &tls[1][1]; void threadFunc(int num)() { writeln(num, " shared ptr: ", p1); writeln(num, " thread local ptr: ", cast(int*)p2); } auto thr1 = new Thread(&threadFunc!1); thr1.start(); auto thr2 = new Thread(&threadFunc!2); thr2.start(); thr1.join(); thr2.join(); } therads will print same "shared ptr" value but different "thread local ptr" However this future is disharmonious with language design I think. Other way: disallow all of tls static initialized values. shared int[] a = [1,2,3]; //OK _gshared int[] b = [1,2,3]; //OK const int[] c = [1,2,3]; //OK int[] d = [1,2,3]; //Disallowed int[] e;//OK static this() { e = [1,2,3]; //If e value will be allocated in heap this code doesn't break type system. } The same applies to classes, pointers and associative arrays in future. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
