Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
September 15, 2015 Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Under Windows this works fine but under Linux I got a runtime error. this could be reduced to : --- import std.parallelism; alias CallBack = void function(void*); class Foo { CallBack clbck; void* param; void dotask() { // some heavy processing // tells the caller that some fresh data are available if(clbck) clbck(param); // debugger breaks HERE } void call() { task(&dotask).executeInNewThread; // returns directly but the caller will get a notif when finished } } --- more info about the environment: - linux i386 - the D program is actually a .so and the main thread is the exe that loads this .so. - If i don't use a Task then the program works **fine**. Is it possible to achieve this in a cross platform-way ? How can i get in phase with the main big thread at the end of my task ? |
September 16, 2015 Re: Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBasile | On Tuesday, 15 September 2015 at 23:49:23 UTC, BBasile wrote: > Under Windows this works fine but under Linux I got a runtime error. > > this could be reduced to : > [...] If it can help to understand the problem, here is the unreducted case: https://github.com/BBasile/Coedit/blob/master/cedast/src/ast.d#L343 |
September 16, 2015 Re: Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBasile | On 09/15/2015 04:49 PM, BBasile wrote: > Under Windows this works fine but under Linux I got a runtime error. Can it be because 'param' is invalid at the time clbck is called? The following program works under Linux. However, removing thread_joinAll() is a bug: import std.parallelism; import std.stdio; alias CallBack = void function(void*); class Foo { CallBack clbck; void* param; void dotask() { // some heavy processing // tells the caller that some fresh data are available if(clbck) clbck(param); // debugger breaks HERE } void call() { task(&dotask).executeInNewThread; // returns directly but the caller will get a notif when finished } } void handler(void* p) { writefln("Finishing with %s at %s", *(cast(int*)p), p); } void main() { auto foo = new Foo(); foo.clbck = &handler; int i = 42; foo.param = &i; foo.call(); import core.thread; thread_joinAll(); } Ali |
September 16, 2015 Re: Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 16 September 2015 at 18:19:07 UTC, Ali Çehreli wrote: > On 09/15/2015 04:49 PM, BBasile wrote: >> Under Windows this works fine but under Linux I got a runtime error. > > Can it be because 'param' is invalid at the time clbck is called? No the callback and its user parameter are set at the same time. > The following program works under Linux. However, removing thread_joinAll() is a bug: I got to try `thread_joinAll`. The main thread is not a D program so i cant call `thread_joinAll` that simply. Maybe as an additonal dll export but in this case if `thread_joinAll` does something with the Runtime (?) it's quite probable that it won't have an effect. :/ |
September 16, 2015 Re: Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBasile | On 09/16/2015 02:01 PM, BBasile wrote: > On Wednesday, 16 September 2015 at 18:19:07 UTC, Ali Çehreli wrote: >> On 09/15/2015 04:49 PM, BBasile wrote: >>> Under Windows this works fine but under Linux I got a runtime error. >> >> Can it be because 'param' is invalid at the time clbck is called? > > No the callback and its user parameter are set at the same time. I don't want to sound like insisting on my idea but I was more concerned about the time when param's life ended. The callback is just a function pointer. Functions never die, so there is no concern with that. However, the actual variable that 'param' is pointing at may have been gone before the callback is executed. >> The following program works under Linux. However, removing >> thread_joinAll() is a bug: > > I got to try `thread_joinAll`. > > The main thread is not a D program so i cant call `thread_joinAll` that > simply. Maybe as an additonal dll export but in this case if > `thread_joinAll` does something with the Runtime (?) it's quite probable > that it won't have an effect. :/ In my code, thread_joinAll() simply made main() wait until the thread finished. Otherwise, if main() ended before the thread, the int data would be invalid when the callback was using a pointer to its (old) location. Ali |
September 17, 2015 Re: Runtime error when calling a callback in a parallel Task | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 16 September 2015 at 22:30:26 UTC, Ali Çehreli wrote: > On 09/16/2015 02:01 PM, BBasile wrote: > > On Wednesday, 16 September 2015 at 18:19:07 UTC, Ali Çehreli > wrote: > >> On 09/15/2015 04:49 PM, BBasile wrote: > >>> Under Windows this works fine but under Linux I got a > runtime error. > >> > >> Can it be because 'param' is invalid at the time clbck is > called? > > > > No the callback and its user parameter are set at the same > time. > > I don't want to sound like insisting on my idea but I was more concerned about the time when param's life ended. The callback is just a function pointer. Functions never die, so there is no concern with that. However, the actual variable that 'param' is pointing at may have been gone before the callback is executed. > > >> The following program works under Linux. However, removing > >> thread_joinAll() is a bug: > > > > I got to try `thread_joinAll`. > > > > The main thread is not a D program so i cant call > `thread_joinAll` that > > simply. Maybe as an additonal dll export but in this case if > > `thread_joinAll` does something with the Runtime (?) it's > quite probable > > that it won't have an effect. :/ > > In my code, thread_joinAll() simply made main() wait until the thread finished. Otherwise, if main() ended before the thread, the int data would be invalid when the callback was using a pointer to its (old) location. > > Ali No, the param is fine. As said initially: > If i don't use a Task then the program works **fine**. There is a synchronization problem and only under Linux. Here is a small program that illustrates better the pattern (based on your previous sample): --- import std.parallelism; alias CallBack = void function(void*); class Foreground { private Background back; bool dataAvailable; this() { back = new Background; back.clbck = &backgroundFinished; back.param = cast(void*) this; } public void something() { dataAvailable = false; back.call; } private static void backgroundFinished(void* param) { with (cast(Foreground) param) dataAvailable = true; } // lock the access until the background thread notifies that // interestingData is ready. Background access() { if (dataAvailable) return back; else return null; } } class Background { CallBack clbck; void* param; private void dotask() { // processing on interestingData if(clbck) clbck(param); // debugger breaks HERE } void call() { task(&dotask).executeInNewThread; } public uint interestingData; } void main() { auto fore = new Foreground(); import std.random; while (true) // you'll have to kill by hand ! { // maybe access will be locked if (uniform(0,100) > 95) fore.something; // try to see if access is readable if (uniform(0,100) > 20) if (fore.access) {/*can use fore.access.interesting data*/} } } --- a class 'A' operating in the main thread is linked to a background class 'B' that makes some threaded updates. Other classes operating in the main thread can also have an access to the backgound class B but only through 'A' and if 'A' doesn't lock the access. The access is locked when 'B' is updating in a Thread and until 'B' notifies 'A' that the data are ready. I use a notification because I'm afraid of the results that other classes could get when exploiting the 'B' interstingData. They only **read** them. |
Copyright © 1999-2021 by the D Language Foundation