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.