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