On Sun, 27 Jul 2014 08:51:29 GMT, Drasha wrote:

Hi,

I would like to ask you for an advice. In my application, I am going to have several groups of clients, that are logically separated. I want each group to run in a separate thread, because these groups can have very uneven CPU requirements and I don't want one group to block another.

I have done it using a combination of vibe.d and std.concurrency.

Each launched thread has this kind of processing loop:

while(!mustFinish)
{
  // Process events from controlling thread
  std.concurrency.receiveTimeout( 0.msecs,
    ...
  );
  // Process tasks
  processEvents();
}

Now, I would like to ask you two questions:

  • Is this a sensible approach, or is it noticeably suboptimal?
  • I have noticed that from the last time I checked vibe.d has advanced its concurrency implementation. Should/can I do this using just the vibe.d code without mixing in the std.concurrency module?

Thank you.

Cheers, Drasha

The current application should work fine, but has the disadvantage of using up all CPU time. I'd say that currently the best approach would indeed be to swap std.concurrency for vibe.core.concurrency (until Phobos#1910 is merged). In this case you would just have to start up a task in each thread to handle incoming messages.

For that, you could either actually start up a thread for each process, or use the worker thread pool (with one thread per available hardware thread) along with some yield() calls during time consuming CPU computations. The latter would be the most efficient:

void process1Function()
{
    while (true) {
        receive((int num) {
            // ...
        });
    }
}

auto p1task = runWorkerTaskH(&process1Function);
send(p1task, 42); // send some message

If you use manual threads, things get slightly more complicated, because the task handle needs to be passed back manually:

void process1Function(Task parent)
{
    runTask({
        send(parent, Task.getThis());
        while (true) {
            receive((int num) {
                // ...
            });
        }
    });
    runEventLoop();
}

runTask({
    auto thishandle = Task.getThis();
    auto th = new Thread({ process1Function(thishandle); });
    th.start();
    auto handle = receiveOnly!Task();
    send(handle, 42);
});