Example on how to spawn a thread using a class method?

Ali Çehreli acehreli at yahoo.com
Mon Jun 17 10:13:37 PDT 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



More information about the Digitalmars-d-learn mailing list