Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop a async evaluating function on timeout?

say we have a simple async call we want to kill/terminate/eliminate on timeout

// future::wait_for
#include <iostream>       // std::cout
#include <future>         // std::async, std::future
#include <chrono>         // std::chrono::milliseconds

// a non-optimized way of checking for prime numbers:
bool is_prime (int x) {
  for (int i=2; i<x; ++i) if (x%i==0) return false;
  return true;
}

int main ()
{
  // call function asynchronously:
  std::future<bool> fut = std::async (is_prime,700020007); 

  // do something while waiting for function to set future:
  std::cout << "checking, please wait";
  std::chrono::milliseconds span (100);
  while (fut.wait_for(span)==std::future_status::timeout)
    std::cout << '.';

  bool x = fut.get();

  std::cout << "\n700020007 " << (x?"is":"is not") << " prime.\n";

  return 0;
}

we want to kill it as soon as first timeout happens. Cant find a method in future.

The closest I could find to stop a running task was std::packaged_task reset method yet it does not say if it can interrupt a running task. So how one kills a task running asyncrinusly not using boost thread or other non stl libraries?

like image 910
DuckQueen Avatar asked Mar 01 '26 11:03

DuckQueen


1 Answers

It's not possible to stop a std::async out of the box... However, You can do this, pass a bool to terminate the is_prime method and throw an exception if there is a timeout:

// future::wait_for
#include <iostream>       // std::cout
#include <future>         // std::async, std::future
#include <chrono>         // std::chrono::milliseconds  

// A non-optimized way of checking for prime numbers:
bool is_prime(int x, std::atomic_bool & run) {
    for (int i = 2; i < x && run; ++i)
    {
        if (x%i == 0) return false;
    }

    if (!run)
    {
        throw std::runtime_error("timed out!");
    }

    return true;
}

int main()
{
    // Call function asynchronously:
    std::atomic_bool run;
    run = true;
    std::future<bool> fut = std::async(is_prime, 700020007, std::ref(run));

    // Do something while waiting for function to set future:
    std::cout << "checking, please wait";
    std::chrono::milliseconds span(100);
    while (fut.wait_for(span) == std::future_status::timeout)
    {
        std::cout << '.';
        run = false;
    }

    try
    {
        bool x = fut.get();
        std::cout << "\n700020007 " << (x ? "is" : "is not") << " prime.\n";
    }
    catch (const std::runtime_error & ex)
    {
        // Handle timeout here
    }

    return 0;
}

Why being able to stop thread is bad.

Stopping threads at an arbitrary point is dangerous and will lead to resource leaks, where resources being pointers, handles to files and folders, and other things the program should do.

When killing a thread, the thread may or may not be doing work. Whatever it was doing, it won’t get to complete and any variables successfully created will not get their destructors called because there is no thread to run them on.

I have outlined some of the issues here.

like image 198
Kent Avatar answered Mar 04 '26 01:03

Kent