Obedient threads

Chris via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Oct 2 13:42:49 PDT 2014


On Thursday, 2 October 2014 at 18:08:40 UTC, Ali Çehreli wrote:
> 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

Thanks Ali, you're a legend! I was actually thinking of creating 
a separate thread as an event listener instead of using main. 
I'll try that now. Somehow the 1.msecs solution doesn't seem 
clean enough.


More information about the Digitalmars-d-learn mailing list