Thread overview
Example on how to spawn a thread using a class method?
Jun 17, 2013
Gary Willoughby
Jun 17, 2013
Ali Çehreli
Jun 18, 2013
Gary Willoughby
June 17, 2013
Anyone got an example on how to spawn a thread using a class method?

I want to wrap behaviour in a class and launch one of its methods using a thread. Once the method is running i want to interact with it from the main program by calling other methods which send the thread messages.

I'm stumbling at the first hurdle by not understanding how to use a class method to spawn a thread.

Any ideas appreciated.
June 17, 2013
On 06/17/2013 03:22 AM, Gary Willoughby wrote:

> Anyone got an example on how to spawn a thread using a class method?
>
> I want to wrap behaviour in a class and launch one of its methods using
> a thread. Once the method is running i want to interact with it from the
> main program by calling other methods which send the thread messages.
>
> I'm stumbling at the first hurdle by not understanding how to use a
> class method to spawn a thread.
>
> Any ideas appreciated.

The address of the member function on a particular class instance is a delegate. You can pass such a delegate to the thread function. Of course, 'shared' is important:

import std.stdio;
import std.string;
import std.concurrency;

shared class C
{
    int i;

    this(int i)
    {
        this.i = i;
    }

    string foo(int multiplier) const
    {
        return format("%s x %s = %s", i, multiplier, i * multiplier);
    }
}

// The signature of the delegate matches the member function
void workerWithDelegate(string delegate(int) shared dg)
{
    // Receive the argument for the member function
    int multiplier = receiveOnly!int();

    // Call the member function on the specific object that it is tied to
    string result = dg(multiplier);

    // (Note: ownerTid is new in 2.063)
    ownerTid.send(result);
}

void main()
{
    auto c = new shared(C)(42);

    // &c.foo makes a delegate that is tied to the specific object 'c'
    Tid worker = spawn(&workerWithDelegate, &c.foo);
    worker.send(10);

    string result = receiveOnly!string();
    writefln(`My worker gave me "%s"`, result);
}

However, if you want to tie "calling foo()" on any object, then you must either wrap that logic in a function (or delegate), conveniently with the lambda syntax. Here are the minimal changes to the above:

import std.stdio;
import std.string;
import std.concurrency;

shared class C
{
    int i;

    this(int i)
    {
        this.i = i;
    }

    string foo(int multiplier) const
    {
        return format("%s x %s = %s", i, multiplier, i * multiplier);
    }
}

// The signature of the delegate matches the member function. However, it is
// not the direct call to the member function; the lambda will call the member
// function.
void workerWithDelegate(string function(shared(C), int) dg)
{
    // Receive both the object and the argument for the member function call
    auto message = receiveOnly!(shared(C), int)();

    shared(C) c = message[0];
    int multiplier = message[1];

    // Call the member function on the object
    string result = dg(c, multiplier);

    // (Note: ownerTid is new in 2.063)
    ownerTid.send(result);
}

void main()
{
    // This lambda knows what member function to call. It will get the actual
    // object at run time.
    Tid worker = spawn(&workerWithDelegate,
                       (shared(C) c, int multiplier) => c.foo(multiplier));

    // A new object goes with each message along with the multiplier
    worker.send(new shared(C)(42), 10);

    string result = receiveOnly!string();
    writefln(`My worker gave me "%s"`, result);
}

Ali

June 18, 2013
Ah right, so you use a function as a wrapper around the delegate. Thanks.