Fiber and Thread Communication

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Apr 9 17:17:24 PDT 2016


On 04/08/2016 02:42 PM, Dicebot wrote:

 >> Thanks Dicebot. I don't think the included
 >> std.concurrency.FiberScheduler has support for message passing because
 >> FiberScheduler.spawn does not return a Tid. If so, I don't see how
 >> it's possible to send messages between fibers.
 >>
 >> Ali
 >
 > Looks like a (funny) oversight.

Sorry, I misled you. :)

 > Note that you get it for get fiber via
 > 
https://github.com/D-Programming-Language/phobos/blob/master/std/concurrency.d#L1337 

 > (and FiberScheduler specifically extends Fiber to add ThreadInfo to it)
 > but there is no clear way to pass that info to spawn host. I have a
 > feeling that if that code is patched to simply provide Tid, message
 > passing will just magically work. Needs to be checked though.

It turns out, instead of calling scheduler.spawn() directly, the program 
sets the __gshared 'scheduler' variable first and then calls spawn() as 
usual, which does return that fiber's Tid:

import std.stdio;
import std.concurrency;
import std.range;
import std.algorithm;

struct Done {
}

void workerTask(int id) {
     writefln("workerTask %s started", id);

     bool done = false;
     while (!done) {
         receive(
             (int message) {
                 writefln("workerTask %s received %s", id, message);
                 ownerTid.send(message * id);
             },
             (Done message) {
                 writefln("workerTask %s received Done", id);
                 done = true;
             });

         // Seems not to be needed:
         // scheduler.yield();
     }

     writefln("workerTask %s exiting", id);
}

void mainTask() {
     enum workerCount = 5;
     enum loopCount = 3;

     writeln("mainTask started");

     auto workers = iota(workerCount)
                    .map!(id => spawn(&workerTask, id))
                    .array;

     foreach (i; 0 .. loopCount) {
         foreach (id, worker; workers) {
             worker.send(i);
             auto response = receiveOnly!int();
             assert(response == i * id);
             writefln("mainTask received %s", response);
         }
     }

     writeln("mainTask sending Done messages");

     foreach (worker; workers) {
         worker.send(Done());
     }

     writeln("mainTask exiting");
}

void main() {
     scheduler = new FiberScheduler;
     scheduler.start({
         mainTask();
     });
}

Ali



More information about the Digitalmars-d-learn mailing list