www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Thread/Task cancellation

reply Gjiergji <gjiergji.koleka gmail.com> writes:

async/await equivalent in D (except fibers which are not suitable 
for multi threading), but if I am using threads, what is the D 
idiom to implement cancellation?



```csharp
try
{
    while (!cancellationToken.IsCancellationRequested)
    {
       //do some work
       await SomethingAsync(cancellationToken);
       //do some other work
       await Task.Delay(TimeSpan.FromSeconds(5000), 
cancellationToken);
    }
}
catch (OperationCancelledException e) when (e.Token == 
cancellationToken)
{
    //someone cancelled any of the await calls above, we can 
swallow it or log it
}

```

The question is how do I pass a `cancellationToken` to the calls 
from the loop in order to terminate them before completion. For 
example, I learnt about `Thread.sleep` in phobos, but I cannot 
pass a cancellation token in order to cancel it before the 
intended sleep duration.

Thx.
Jul 28 2023
parent reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Friday, 28 July 2023 at 18:17:18 UTC, Gjiergji wrote:

 async/await equivalent in D (except fibers which are not 
 suitable for multi threading), but if I am using threads, what 
 is the D idiom to implement cancellation?



 ```csharp
 try
 {
    while (!cancellationToken.IsCancellationRequested)
    {
       //do some work
       await SomethingAsync(cancellationToken);
       //do some other work
       await Task.Delay(TimeSpan.FromSeconds(5000), 
 cancellationToken);
    }
 }
 catch (OperationCancelledException e) when (e.Token == 
 cancellationToken)
 {
    //someone cancelled any of the await calls above, we can 
 swallow it or log it
 }

 ```

 The question is how do I pass a `cancellationToken` to the 
 calls from the loop in order to terminate them before 
 completion. For example, I learnt about `Thread.sleep` in 
 phobos, but I cannot pass a cancellation token in order to 
 cancel it before the intended sleep duration.

 Thx.
You could use a thread to check if the token has been sent via message passing, and when it is sent, throw an exception, like this: ```d import std.concurrency; Tid tid; void foo() { try { tid = spawn(&bar); // do stuff } catch(Exception e) { // ... } } void bar() { bool terminate = false; terminate = receiveOnly!bool(); if(terminate) { throw new Exception("Thread terminated"); } } void main() { spawn(&foo); // ... if(needsToTerminateFooForSomeReason) tid.send(true); // ... } ``` This does however, terminate with signal 11 upon sending the terminate signal, and I'm not sure why.
Jul 28 2023
parent Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Friday, 28 July 2023 at 18:52:59 UTC, Ruby The Roobster wrote:
 On Friday, 28 July 2023 at 18:17:18 UTC, Gjiergji wrote:

 no async/await equivalent in D (except fibers which are not 
 suitable for multi threading), but if I am using threads, what 
 is the D idiom to implement cancellation?



 ```csharp
 try
 {
    while (!cancellationToken.IsCancellationRequested)
    {
       //do some work
       await SomethingAsync(cancellationToken);
       //do some other work
       await Task.Delay(TimeSpan.FromSeconds(5000), 
 cancellationToken);
    }
 }
 catch (OperationCancelledException e) when (e.Token == 
 cancellationToken)
 {
    //someone cancelled any of the await calls above, we can 
 swallow it or log it
 }

 ```

 The question is how do I pass a `cancellationToken` to the 
 calls from the loop in order to terminate them before 
 completion. For example, I learnt about `Thread.sleep` in 
 phobos, but I cannot pass a cancellation token in order to 
 cancel it before the intended sleep duration.

 Thx.
[SNIP]
 You could use a thread to check if the token has been sent via 
 message passing, and when it is sent, throw an exception, like 
 this:
 This does however, terminate with signal 11 upon sending the 
 terminate signal, and I'm not sure why.
Ignore my above code, Here is something that should work: ```d import std.concurrency; void foo() { try { auto tid = spawnLinked(&bar); ownerTid.send(tid); // do stuff // ... auto c = receiveTimeout(0.msecs, (ubyte a) {}); // Since bar is linked, this will throw an exception when bar terminates } catch(Exception e) { // Do whatever with the exception message, but it terminates the function execution. } } void bar() { bool terminate = false; terminate = receiveOnly!bool(); } void main() { spawn(&foo); Tid tid = receiveOnly!Tid(); // ... if(needsToTerminateFooForSomeReason) tid.send(true); // ... } ``` This is the only way I could think of doing this, since exceptions don't travel up the threads.
Jul 28 2023