digitalmars.D.learn - concurrency problem with pointers
- evilrat (34/34) Jul 18 2013 i hate asking for help, but... now i'm pushed in the corner. so
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/7) Jul 18 2013 Can you show it with a short program without using platform specific
- evilrat (7/13) Jul 19 2013 that's who i am. long story, but in short, people hated when i
- John Colvin (5/22) Jul 19 2013 I can't get that to compile, I keep getting
- evilrat (3/11) Jul 19 2013 no you don't. this is because of the definition of GLFWwindow in
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (47/50) Jul 19 2013 Further reduced by removing the need for derelict3 and glfw:
- evilrat (14/35) Jul 19 2013 unfortunately both variants fails for me, i think this is because
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (17/19) Jul 19 2013 Further reduced:
- evilrat (7/20) Jul 19 2013 i don't think this is compiler bug, it's just how it works. yet
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (17/22) Jul 19 2013 But what code needs toHash and others for the struct type even though we...
- evilrat (8/22) Jul 19 2013 maybe you are right about Variant, and yet it still not compiler
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (61/63) Jul 19 2013 That would be wrong. Yes the compiler needs the definition of the struct...
- evilrat (4/12) Jul 20 2013 maybe it should. but it doesn't matters what i think about how it
- Sean Kelly (9/11) Jul 18 2013 "shared", and i need it in another thread to make opengl context current...
- evilrat (3/7) Jul 19 2013 sure cast to size_t and back works, but can shoot in the leg
i hate asking for help, but... now i'm pushed in the corner. so here is my problem: i have struct with handle, and i need to send this struct or handle to second thread, all fine but feeding this struct or handle to send results in multiple errors(mostly complains about thread local data). and unfortunatelly shared and __gshared doesn't helps(complains about unknown size of handle). well, i wish i could describe in details without code but... here is simplified example -------- void main() { MyData data; // load data ... MyWindow wnd(data); wnd.show(); auto tid = spawn(&newViewThread); send(tid, wnd); } // struct because i want benefit from RAII, but if necessary could switch to class struct MyWindow { this ( MyData data ) { ... } // WINDOW defined as struct but has no size WINDOW* handle; } // 3rd party func to get window WINDOW* createWindow(...); ---------- shortly speaking, WINDOW is pointer to window in C library so it's "shared", and i need it in another thread to make opengl context current in that thread, but compiler simply doesn't allow me to do anything with that, and i can't change definition since it's 3rd party bindings. any suggestions?
Jul 18 2013
On 07/18/2013 08:29 AM, evilrat wrote:i hate asking for helpPlease do so. Otherwise we can't learn from others' issues. :)well, i wish i could describe in details without codeCan you show it with a short program without using platform specific definitions? Ali
Jul 18 2013
On Thursday, 18 July 2013 at 17:23:20 UTC, Ali Çehreli wrote:On 07/18/2013 08:29 AM, evilrat wrote:that's who i am. long story, but in short, people hated when i ask something and after few minutes i find solution. i bother everyone ;(i hate asking for helpPlease do so. Otherwise we can't learn from others' issues. :)here is reduced example without platform-specific stuff, requires derelict3 and glfw. http://pastebin.com/rhB14YNswell, i wish i could describe in details without codeCan you show it with a short program without using platform specific definitions?
Jul 19 2013
On Friday, 19 July 2013 at 15:16:23 UTC, evilrat wrote:On Thursday, 18 July 2013 at 17:23:20 UTC, Ali Çehreli wrote:I can't get that to compile, I keep getting Derelict3/import/derelict/glfw3/types.d(290): Error: struct derelict.glfw3.types.GLFWwindow unknown size I suspect I'm compiling wrong somehow.On 07/18/2013 08:29 AM, evilrat wrote:that's who i am. long story, but in short, people hated when i ask something and after few minutes i find solution. i bother everyone ;(i hate asking for helpPlease do so. Otherwise we can't learn from others' issues. :)here is reduced example without platform-specific stuff, requires derelict3 and glfw. http://pastebin.com/rhB14YNswell, i wish i could describe in details without codeCan you show it with a short program without using platform specific definitions?
Jul 19 2013
On Friday, 19 July 2013 at 15:35:27 UTC, John Colvin wrote:On Friday, 19 July 2013 at 15:16:23 UTC, evilrat wrote:no you don't. this is because of the definition of GLFWwindow in derelict3 (it's really predefined as struct, not void*)here is reduced example without platform-specific stuff, requires derelict3 and glfw. http://pastebin.com/rhB14YNsI can't get that to compile, I keep getting Derelict3/import/derelict/glfw3/types.d(290): Error: struct derelict.glfw3.types.GLFWwindow unknown size I suspect I'm compiling wrong somehow.
Jul 19 2013
On 07/19/2013 08:16 AM, evilrat wrote:here is reduced example without platform-specific stuff, requires derelict3 and glfw. http://pastebin.com/rhB14YNsFurther reduced by removing the need for derelict3 and glfw: import std.stdio; import std.concurrency; import core.thread; alias GLFWwindow = void; struct Window { void create() { auto tid = spawn(&runNewView); send(tid, _wnd ); // <-- ERROR thread_joinAll(); } GLFWwindow* _wnd; } void runNewView() { while ( true ) { receive ( (string msg) { writeln(msg); }, (const(GLFWwindow*) window) { } ); } } void main() { auto window = Window(); // runs main loop window.create(); } Error: static assert "Aliases to mutable thread-local data not allowed." instantiated from here: send!(void*) Is that the problem? (If so, why don't you say so? ;)) Then there are two solutions: a) Make _wnd a shared(GLFWwindow): struct Window { // ... shared(GLFWwindow)* _wnd; } The code now compiles. b) As Sean Kelly said, cast to shared before sending: send(tid, cast(shared(GLFWwindow)*)_wnd ); With the b option you may need to change the definition of the receiving delegate to shared as well: (const(shared(GLFWwindow)*) window) { } But that change is not needed in that simple code. Ali P.S. Additionally, the const on the receiving side probably should apply only to what is being pointed at (as opposed to the pointer itself): (const(GLFWwindow)* window) { }
Jul 19 2013
On Friday, 19 July 2013 at 15:36:33 UTC, Ali Çehreli wrote:Error: static assert "Aliases to mutable thread-local data not allowed." instantiated from here: send!(void*) Is that the problem? (If so, why don't you say so? ;)) Then there are two solutions: a) Make _wnd a shared(GLFWwindow): struct Window { // ... shared(GLFWwindow)* _wnd; } The code now compiles. b) As Sean Kelly said, cast to shared before sending: send(tid, cast(shared(GLFWwindow)*)_wnd ); With the b option you may need to change the definition of the receiving delegate to shared as well: (const(shared(GLFWwindow)*) window) { } But that change is not needed in that simple code.unfortunately both variants fails for me, i think this is because GLFWwindow is (pre)defined as struct instead alias void :( maybe there is something to override type definition without modifying 3rd party libraries code? /Users/evilrat/Documents/prog/Derelict3/import/derelict/glfw3/types.d(290): Error: struct derelict.glfw3.types.GLFWwindow unknown size /Users/evilrat/Documents/prog/Derelict3/import/derelict/glfw3/types.d(290): Error: struct derelict.glfw3.types.GLFWwindow no size yet for forward reference anyway thanks to both authors, now i could avoid such problems in the future \0/P.S. Additionally, the const on the receiving side probably should apply only to what is being pointed at (as opposed to the pointer itself): (const(GLFWwindow)* window) { }ah yes, such a shame. i'm sometimes forgot about this little detail :(
Jul 19 2013
On 07/19/2013 09:00 AM, evilrat wrote:i think this is because GLFWwindow is (pre)defined as struct insteadaliasvoid :(Further reduced: import std.concurrency; struct S; void main() { receive((S * p){}); } Error: struct deneme.S is forward referenced when looking for 'toHash' Error: struct deneme.S is forward referenced when looking for 'opCmp' Error: struct deneme.S is forward referenced when looking for 'toString' Error: struct deneme.S unknown size Error: struct deneme.S no size yet for forward reference Error: struct deneme.S unknown size Error: struct deneme.S no size yet for forward reference Ali
Jul 19 2013
On Friday, 19 July 2013 at 17:14:10 UTC, Ali Çehreli wrote:On 07/19/2013 09:00 AM, evilrat wrote:i don't think this is compiler bug, it's just how it works. yet this is another thing one must remember when writing library - never use struct predefenitions(or any other forward refs). so concluding all of this, it is clear this is a derelict library bug, and that we also need something to allow rewrite defenitions at least at module level, if nothing like this already exists.i think this is because GLFWwindow is (pre)defined as structinstead aliasvoid :(Further reduced: import std.concurrency; struct S; void main() { receive((S * p){}); } Error.... Ali
Jul 19 2013
On 07/19/2013 11:07 AM, evilrat wrote:i don't think this is compiler bug, it's just how it works.But what code needs toHash and others for the struct type even though we are just passing a pointer around?yet this is another thing one must remember when writing library - never use struct predefenitions(or any other forward refs). so concluding all of this, it is clear this is a derelict library bug,I am not convinced yet. I think it is something that std.concurrency is doing (perhaps because it relies on Variant?). Otherwise there is no problem with what derelict does. The following code compiles: struct S; void myReceive(void delegate (S *) func) { S * p; func(p); } void main() { myReceive((S * p){}); } Ali
Jul 19 2013
On Friday, 19 July 2013 at 18:25:26 UTC, Ali Çehreli wrote:On 07/19/2013 11:07 AM, evilrat wrote:maybe you are right about Variant, and yet it still not compiler bug, but phobos bug. rewriting std.variant and std.concurrency just because of forward refs is no go. i think problem is that with a struct we can't just generate code for this methods(toHash,opCmp,etc) by comparing its address, even if it's not extern(C/C++) and not found by linker, or do we actually could?i don't think this is compiler bug, it's just how it works.But what code needs toHash and others for the struct type even though we are just passing a pointer around?yet this is another thing one must remember when writing library - neveruse structpredefenitions(or any other forward refs). so concluding all of this, it is clear this is a derelictlibrary bug, I am not convinced yet. I think it is something that std.concurrency is doing (perhaps because it relies on Variant?). Otherwise there is no problem with what derelict does. The following code compiles:
Jul 19 2013
On 07/19/2013 11:39 AM, evilrat wrote:i think problem is that with a struct we can't just generate code for this methods(toHash,opCmp,etc) by comparing its addressThat would be wrong. Yes the compiler needs the definition of the struct to generate toHash, opCmp, and toString but note that there is no expression that needs S in that sample code. The code uses a pointer to S, which happens to have trivial toHash, opCmp, and toString. I think now I see where the problem is coming from. Note that the three "compiles" lines below do exercise toHash, opCmp, and toString on S*. import std.stdio; struct S; void main() { S* p0, p1; int[S*] arr; arr[p0] = 0; // compiles writefln("%s", p0); // compiles writeln(p0 < p1); // compiles writeln(p0.toString()); // Error: struct S is forward referenced } However, calling toString() directly on the pointer naturally forwards the call to S and that requires the complete definition of the struct. This seems to be a problem with any template that has to work with pointers. The following template cannot work with a pointer: import std.stdio; struct S; void foo(T)(T val) { writeln("%s", val.toString()); // ERROR } void main() { S * p; foo(p); } So, the solution is to do something like the following: import std.stdio; struct S; void foo(T)(T val) { static if (is (T : U*, U)) { writefln("(%s)%s", T.stringof, val); } else { writefln("%s", val.toString()); } } void main() { S * p; foo(p); } And I think the following code in std/concurrency.d is the reason: ( Variant val ) // ... throw new MessageMismatch( format("Unexpected message type: expected '%s', got '%s'", exp, val.type.toString())); } ); val.type returns a TypeInfo and it seems like there is no TypeInfo special for pointers to incomplete types. Shouldn't there be? Ali
Jul 19 2013
On Friday, 19 July 2013 at 19:05:27 UTC, Ali Çehreli wrote:This seems to be a problem with any template that has to work with pointers. The following template cannot work with a pointer: ... val.type returns a TypeInfo and it seems like there is no TypeInfo special for pointers to incomplete types. Shouldn't there be? Alimaybe it should. but it doesn't matters what i think about how it should be, i just hope D would be user friendly, and current situation with that making it quite not so friendly.
Jul 20 2013
On Jul 18, 2013, at 8:29 AM, evilrat <evilrat666 gmail.com> wrote:=20 shortly speaking, WINDOW is pointer to window in C library so it's ="shared", and i need it in another thread to make opengl context current = in that thread, but compiler simply doesn't allow me to do anything with = that, and i can't change definition since it's 3rd party bindings. any = suggestions? In short, you're trying to send a pointer via std.concurrency. The = easiest way is to cast it to/from shared. Otherwise, you'd need to make = it an opaque type like a size_t rather than a type D can tell is a = reference.=
Jul 18 2013
On Thursday, 18 July 2013 at 23:36:34 UTC, Sean Kelly wrote:In short, you're trying to send a pointer via std.concurrency. The easiest way is to cast it to/from shared. Otherwise, you'd need to make it an opaque type like a size_t rather than a type D can tell is a reference.sure cast to size_t and back works, but can shoot in the leg later anytime :(
Jul 19 2013