Obedient threads

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Oct 2 11:08:40 PDT 2014


On 10/02/2014 06:49 AM, Chris wrote:
> On Thursday, 2 October 2014 at 13:05:00 UTC, ketmar via
> Digitalmars-d-learn wrote:
>> On Thu, 02 Oct 2014 11:36:06 +0000
>> Chris via Digitalmars-d-learn <digitalmars-d-learn at puremagic.com> wrote:
>>
>> you can use receiveTimeout! to check if there is some message available.
>
> That won't do. It blocks the main thread too (for the duration of
> timeout), and it might abandon the thread too early. If you do it like
> in Ali's example[1], the main thread is blocked in the sense that it
> does not listen to input.
>
> [1] http://ddili.org/ders/d.en/concurrency.html

To add to what ketmar said, even 0.msecs works.

In such a case moving the other tasks out of the main thread may be a 
better option. main can safely block on the message queue while another 
thread interacts with the outside world. It would be a cleaner event 
loop that way.

I've just improved that example to interact with the user. The worker 
produces a random message periodically. The user can ask for the most 
recent message by entering "yes". (I made it so that reading the message 
also clears it.)

import std.stdio;
import std.concurrency;
import core.thread;
import std.string;
import std.random;
import std.array;

void workerFunc(size_t count, Duration duration)
{
     writefln("There will be %s messages every %s.", count, duration);

     foreach (i; 0 .. count) {
         Thread.sleep(duration);
         ownerTid.send(format("message %s: %s", i, uniform(0, 100)));
     }

     writeln("workerFunc exiting");
}

struct ResultPlease
{}

void interactor()
{
     bool done = false;

     while (!done) {
         write("Would you like to see the result? ");
         string response = readln.chomp;

         if (response == "yes") {
             ownerTid.send(ResultPlease(), thisTid);
             const result = receiveOnly!string();

             if (result.empty) {
                 writeln("Sorry, no result yet.");

             } else {
                 writefln(`The result is "%s"`, result);
             }

         } else {
             writeln("Ok, no more interaction. Bye.");
             done = true;
         }
     }
}

void main()
{
     spawnLinked(&workerFunc, 4, 5.seconds);
     spawnLinked(&interactor);

     string result;
     Tid[] completed;

     while (completed.length < 2) {
         receive(
             (string message) {
                 result = message;
             },

             (ResultPlease request, Tid requestor) {
                 requestor.send(result);
                 result = "";
             },

             (LinkTerminated e) {
                 completed ~= e.tid;
             }
         );
     }
}

Ali



More information about the Digitalmars-d-learn mailing list