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.

Reply via email to