www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Async messages to a thread.

reply "lindenk" <ztaticnull gmail.com> writes:
Hello!
This is partially a general question as I don't know what this is 
called or if it exists. Say for example I want to do something 
like the following -

import std.concurrency;

void main()
{
     void foo() {
         try
         {
             while(true)
             {
                  do_some_blocking_function();
             }
         } catch(GotAMessage msg){}

         // clean up
     };

     tid = spawn(&foo, thisTid);

     // do stuff / wait for some condition

     send(tid, "STAHP!");
}

One solution I've used in the past is setting a timeout for the 
blocking function then polling to see if the thread should exit. 
The disadvantage is it causes extra, unnecessary checking and has 
a delay before it gets the message and exits.

This is a fairly simple example but the idea should be the same, 
is there a way to pass a message or signal to a thread to cause 
it to branch to some other location?
Jul 29 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 29 July 2013 at 15:28:45 UTC, lindenk wrote:
 Hello!
 This is partially a general question as I don't know what this 
 is called or if it exists. Say for example I want to do 
 something like the following -

 import std.concurrency;

 void main()
 {
     void foo() {
         try
         {
             while(true)
             {
                  do_some_blocking_function();
             }
         } catch(GotAMessage msg){}

         // clean up
     };

     tid = spawn(&foo, thisTid);

     // do stuff / wait for some condition

     send(tid, "STAHP!");
 }

 One solution I've used in the past is setting a timeout for the 
 blocking function then polling to see if the thread should 
 exit. The disadvantage is it causes extra, unnecessary checking 
 and has a delay before it gets the message and exits.

 This is a fairly simple example but the idea should be the 
 same, is there a way to pass a message or signal to a thread to 
 cause it to branch to some other location?
import std.concurrency; import core.time; void foo(Tid parent) { bool run = true; while(run) { //do_some_blocking_function(); receiveTimeout(dur!"msecs"(0), (string s){if(s == "STAHP!") run = false;} ); } // clean up send(parent, "done"); } void main() { auto tid = spawn(&foo, thisTid); // do stuff / wait for some condition send(tid, "STAHP!"); auto msg = receiveOnly!(string)(); assert(msg == "done"); }
Jul 29 2013
parent reply "lindenk" <ztaticnull gmail.com> writes:
 void foo(Tid parent) {
     bool run = true;
     while(run)
     {
          //do_some_blocking_function();
          receiveTimeout(dur!"msecs"(0),
              (string s){if(s == "STAHP!") run = false;}
          );
     }

     // clean up
     send(parent, "done");
 }


 void main()
 {
     auto tid = spawn(&foo, thisTid);

     // do stuff / wait for some condition

     send(tid, "STAHP!");
     auto msg = receiveOnly!(string)();
     assert(msg == "done");
 }
Ah, no I mean, what if do_some_blocking_function blocks for some indeterminate amount of time. I would like it to exit even when it is currently blocking (as it could be unpredictable when it will stop blocking).
Jul 29 2013
next sibling parent reply "lindenk" <ztaticnull gmail.com> writes:
After a bit more research it looks like everyone else uses -

while(checkIfRunning())
{
     // block with timeout
}

which leads me to believe this might not be possible or standard. 
Although, should something along the lines of this be possible?

Process p = new Process();
p.doTask(p.func()); //create new thread and start function

// do stuff until this needs to exit

p.stop(); // halt running function,
p.cleanup(); // call a clean up function for func's resources
p.kill(); // forcibly kill the thread


If this is possible and/or not a bad idea, how can I accomplish 
this in D? (And if there isn't really a way, I feel like D's 
scope(exit) and such should work nicely with it).
Jul 29 2013
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Jul 29, 2013, at 10:07 AM, lindenk <ztaticnull gmail.com> wrote:

 After a bit more research it looks like everyone else uses -
=20
 while(checkIfRunning())
 {
    // block with timeout
 }
=20
 which leads me to believe this might not be possible or standard. =
Although, should something along the lines of this be possible? It sounds like you're maybe doing socket IO? In those cases, you can = open a pipe for signaling. select() on whatever other socket plus the = read end of the pipe, and if you want to break out of the blocking = select() call, write a byte to the pipe. Ultimately, std.concurrency = should get some socket integration so data can arrive as messages, but = that will never be as efficient as the approach I've described.
 Process p =3D new Process();
 p.doTask(p.func()); //create new thread and start function
=20
 // do stuff until this needs to exit
=20
 p.stop(); // halt running function,
 p.cleanup(); // call a clean up function for func's resources
 p.kill(); // forcibly kill the thread
Forcibly killing threads tends to be a pretty bad idea if you intend to = keep running after the thread is killed. It can even screw up attempts = at a clean shutdown.=
Jul 29 2013
parent "lindenk" <ztaticnull gmail.com> writes:
On Monday, 29 July 2013 at 17:26:55 UTC, Sean Kelly wrote:
 On Jul 29, 2013, at 10:07 AM, lindenk <ztaticnull gmail.com> 
 wrote:

 After a bit more research it looks like everyone else uses -
 
 while(checkIfRunning())
 {
    // block with timeout
 }
 
 which leads me to believe this might not be possible or 
 standard. Although, should something along the lines of this 
 be possible?
It sounds like you're maybe doing socket IO? In those cases, you can open a pipe for signaling. select() on whatever other socket plus the read end of the pipe, and if you want to break out of the blocking select() call, write a byte to the pipe. Ultimately, std.concurrency should get some socket integration so data can arrive as messages, but that will never be as efficient as the approach I've described.
 Process p = new Process();
 p.doTask(p.func()); //create new thread and start function
 
 // do stuff until this needs to exit
 
 p.stop(); // halt running function,
 p.cleanup(); // call a clean up function for func's resources
 p.kill(); // forcibly kill the thread
Forcibly killing threads tends to be a pretty bad idea if you intend to keep running after the thread is killed. It can even screw up attempts at a clean shutdown.
The blocking function will sometimes be socket IO, it's set up to get data from whatever it is set to. That sounds promising though, I could set it up to do that when it is socket IO then have it poll when it isn't. Thanks!
Jul 29 2013
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Jul 29, 2013, at 8:28 AM, lindenk <ztaticnull gmail.com> wrote:
=20
 Ah, no I mean, what if do_some_blocking_function blocks for some =
indeterminate amount of time. I would like it to exit even when it is = currently blocking (as it could be unpredictable when it will stop = blocking). Execute the blocking functions in a separate thread? Really, this = sounds like the kind of thing futures are for. Alternately, maybe the = sequence of blocking functions could call receive periodically, or maybe = be executed in a fiber and yield periodically, etc.=
Jul 29 2013
prev sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 29 July 2013 at 16:19:03 UTC, lindenk wrote:
 void foo(Tid parent) {
    bool run = true;
    while(run)
    {
         //do_some_blocking_function();
         receiveTimeout(dur!"msecs"(0),
             (string s){if(s == "STAHP!") run = false;}
         );
    }

    // clean up
    send(parent, "done");
 }


 void main()
 {
    auto tid = spawn(&foo, thisTid);

    // do stuff / wait for some condition

    send(tid, "STAHP!");
    auto msg = receiveOnly!(string)();
    assert(msg == "done");
 }
Ah, no I mean, what if do_some_blocking_function blocks for some indeterminate amount of time. I would like it to exit even when it is currently blocking (as it could be unpredictable when it will stop blocking).
The blocking function could start in a new thread and do a receiveTimeout periodically, or you could make it stateful (if necessary) and return periodically and be restarted if it hasn't been asked to stop (which is just a very ugly and rudimentary version of what you'd want to do with fibers). Or, if you don't care about making a mess, just kill the thread I guess.
Jul 29 2013