16

I'm confused by something about C++11 std::future. I want to balance work load dynamically, so if there are some processors idle, I create a std::future with std::async to divide the remaining data. It works fine.

std::future<int> f[MAX_CHILD];
for ( each data item ){
    if ( found_idle_processor )
        f[i] = std::async( ... );

    process();
}

// At last, query the result of f.
for ( each future )
    hold = f[i].get();

But sometimes, once some special data items were found, all other data will be discarded and the program should give the final result immediately, then another task will be launched.

std::future<int> f[MAX_CHILD];
for ( each data item ){
    if ( found_idle_processor )
        f[i] = std::async( ... );

    process();

    if ( found_special_item )
        return final_result;
}
// At last, query the result of each f.
for ( each future )
    hold = f[i].get();

But the created f are out of my control, are they still running after return? how can I terminate them to release CPU time they used?

Aean
  • 759
  • 1
  • 6
  • 16
  • 6
    It's simple: You can't. In fact, there is no way of canceling either futures *or* threads in the standard. – Some programmer dude Mar 26 '14 at 06:24
  • I'm targeted on Windows platform, no portability is needed. Platform dependent methods like `TerminateThread( thread->nativeHandle(), 0 )` are also acceptable. But I don't know how to get the native handle either. – Aean Mar 26 '14 at 08:38
  • While you can get the native handle from a `std::thread`, it's not available for `std::future`. Probably because futures doesn't have to be run in a thread. – Some programmer dude Mar 26 '14 at 08:39
  • async is using a thread pool in the MSVC implementation, so it would not be a good idea to terminate one of them. – galop1n Mar 26 '14 at 08:57
  • 5
    Two words: Cooperative cancellation. Check a flag in your worker tasks, and if it's set, terminate them gracefully from within (i.e., just stop the work). – Xeo Mar 26 '14 at 09:32

1 Answers1

19

The C++ standard does not provide a way to cancel a future or stop a thread. There is a reason for that.

There is no way to know if a thread can be stopped safely at some particular moment in time. The thread may have acquired resources which should be finalized. Only the running thread itself knows when it is safe to stop.

Even if the underlying low-level API provides a call to kill any thread at will, this is definitely not a good way to go because of the above-mentioned circumstances.

Traditional solution to this issue is signalling the thread and cancelling it from within. A trivial implementation may be based on a single atomic bool flag.

Sergey K.
  • 24,894
  • 13
  • 106
  • 174
  • Thanks for your answer. AFAIK `pthread` provided a set of methods `pthread_setcanceltype` `pthread_testcancel` and `pthread_cancel` which could terminate a thread safely and easily. So sad to know C++ doesn't have such equivalents. – Aean Mar 31 '14 at 14:07
  • 1
    @Aean: yes, they can terminate the thread. But there is no way, in general, to do it safely from outside without possible side-effects (image termination of a network server thread). – Sergey K. Mar 31 '14 at 14:08
  • https://en.cppreference.com/w/cpp/thread/jthread/request_stop – Sergei Krivonos Jun 22 '23 at 11:10