www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Timeout around function call

reply drathier <forum.dlang.org fi.fo> writes:
What's the obvious way to put a timeout around a function call? 
I'm thinking a 5 or 30 second timeout, and I'm expecting it to 
pretty much never time out.
Sep 22 2020
next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 9/22/20 2:32 AM, drathier wrote:> What's the obvious way to put a 
timeout around a function call? I'm
 thinking a 5 or 30 second timeout, and I'm expecting it to pretty much
 never time out.
I would start a thread and use receiveTimeout(): import std.concurrency; import std.stdio; import std.exception; import core.thread; // Uncomment to see what happens upon time out. // version = doTimeout; void compute(int i) { version (doTimeout) { writeln("The thread is napping."); Thread.sleep(2.seconds); } ownerTid.send(i + 1); } void main() { auto worker = spawn(&compute, 42); const received = receiveTimeout( 1.seconds, (int result) { writefln!"Received the result: %s"(result); } ); enforce(received, "Timed out."); } The thread need not be one-shot: It can continue waiting for more messages until told to stop: import std.concurrency; import std.stdio; import std.exception; import core.thread; // Uncomment to see what happens upon time out. // version = doTimeout; struct Done { } void computer() { bool done = false; while (!done) { receive( (Done _) { done = true; }, (int i) { version (doTimeout) { writeln("The thread is napping."); Thread.sleep(2.seconds); } ownerTid.send(i + 1); } ); } } void main() { // This time we use spawnLinked() so that we will receive // a LinkTerminated message. And the name is different and // the argument will be passed later with send(). auto worker = spawnLinked(&computer); foreach (i; 0 .. 10) { worker.send(i); const received = receiveTimeout( 1.seconds, (int result) { writefln!"Received the result: %s"(result); } ); enforce(received, "Timed out."); } // Tell worker to stop. worker.send(Done()); // Wait for worker to terminate. receiveOnly!LinkTerminated(); } Ali
Sep 22 2020
prev sibling parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Tuesday, 22 September 2020 at 09:32:13 UTC, drathier wrote:
 What's the obvious way to put a timeout around a function call? 
 I'm thinking a 5 or 30 second timeout, and I'm expecting it to 
 pretty much never time out.
You have several options. Either you use the actor model (spawn[Linked]) and send a termination message after a specified time. Or you use a task and check for yourTask.done(). Or you could create a Thread and check isRunning. (You didn't specify what you wanted to happen and if blocking was allowed or not)
Sep 22 2020
parent reply drathier <forum.dlang.org fi.fo> writes:
On Tuesday, 22 September 2020 at 21:55:51 UTC, Imperatorn wrote:
 On Tuesday, 22 September 2020 at 09:32:13 UTC, drathier wrote:
 What's the obvious way to put a timeout around a function 
 call? I'm thinking a 5 or 30 second timeout, and I'm expecting 
 it to pretty much never time out.
You have several options. Either you use the actor model (spawn[Linked]) and send a termination message after a specified time. Or you use a task and check for yourTask.done(). Or you could create a Thread and check isRunning. (You didn't specify what you wanted to happen and if blocking was allowed or not)
Blocking is perfectly fine. I'm wondering if I need things to be shared now or something? Not used to programming with threads. Adding a shared modifier recursively onto every piece of data that needs it is a ton of work though. I don't want to copy the data around since it's many gigabytes, but I'm sure there won't be any data races; main thread will start 2 threads, one for running the timer and one running the function call. The main thread doesn't access the data until both the timer and function call threads have stopped completely.
Sep 23 2020
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 23 September 2020 at 17:33:50 UTC, drathier wrote:
 On Tuesday, 22 September 2020 at 21:55:51 UTC, Imperatorn wrote:
 [...]
Blocking is perfectly fine. I'm wondering if I need things to be shared now or something? Not used to programming with threads. Adding a shared modifier recursively onto every piece of data that needs it is a ton of work though. I don't want to copy the data around since it's many gigabytes, but I'm sure there won't be any data races; main thread will start 2 threads, one for running the timer and one running the function call. The main thread doesn't access the data until both the timer and function call threads have stopped completely.
No. You should not share anything. Personally I would just send a message to request termination or use the solution provided with timeout.
Sep 23 2020
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 9/23/20 1:19 PM, Imperatorn wrote:

 No. You should not share anything. Personally I would just send a
 message to request termination or use the solution provided with timeout.
std.concurrency does not allow "mutable thread-local data"; so one needs to cast to shared (assuming copying is not desired e.g. because it's expensive). I am modifying my second program[1] with these changes: The worker's receive() call mentions an element with shared ints: receive( // .. same as before // New message type: (shared(int)[] arr) { ownerTid.send(arr[0]); } ); The sender casts to shared and receives a shared(int): auto arr = new int[100]; worker.send(cast(shared)arr); writefln!"Received array result: %s"(receiveOnly!(shared(int))()); It is unfortunate that receiveOnly!int does not work because the returned int is just a copy. Well, at least we have a way of distinguishing int from shared(int). Is it useful? Ali [1] https://forum.dlang.org/post/rkdrql$2uht$1 digitalmars.com
Sep 23 2020
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 23 September 2020 at 20:44:51 UTC, Ali Çehreli 
wrote:
 On 9/23/20 1:19 PM, Imperatorn wrote:

 [...]
send a
 [...]
with timeout. [...]
Sorry, I can't see the problem. Could you be more specific about what you want to achieve?
Sep 23 2020
parent reply Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Wednesday, 23 September 2020 at 20:54:51 UTC, Imperatorn wrote:
 On Wednesday, 23 September 2020 at 20:44:51 UTC, Ali Çehreli 
 wrote:
 On 9/23/20 1:19 PM, Imperatorn wrote:

 [...]
send a
 [...]
with timeout. [...]
Sorry, I can't see the problem. Could you be more specific about what you want to achieve?
Oops, I meant to reply to drathier
Sep 23 2020
parent drathier <forum.dlang.org fi.fo> writes:
On Wednesday, 23 September 2020 at 20:58:00 UTC, Imperatorn wrote:
 On Wednesday, 23 September 2020 at 20:54:51 UTC, Imperatorn 
 wrote:
 On Wednesday, 23 September 2020 at 20:44:51 UTC, Ali Çehreli 
 wrote:
 On 9/23/20 1:19 PM, Imperatorn wrote:

 [...]
send a
 [...]
with timeout. [...]
Sorry, I can't see the problem. Could you be more specific about what you want to achieve?
Oops, I meant to reply to drathier
I need to: - call a side-effect-free fn with a huge argument that I don't want to copy; this argument is then returned mostly unmodified wrapped in a new value - stop executing it if it runs for more than x seconds - get the return value from it if it finishes within x seconds (99.9% of time time) - let the main thread know what happened - the main thread should block until the fn call returns - the fn call should for sure stop executing before the main thread carries on - the size and complexity of the fn makes it pretty much impossible to add timeout checks everywhere to make it exit nicely; I need to kill it to be sure I didn't miss a case
Sep 27 2020