My problem is that I have multiple threads, they are stored in some container, and I need to know when a thread at a certain position finished. On windows I would do something like:
HANDLE handles[3];
//handles were initialized
DWORD finishingThread = WaitForMultipleObjects(3, handles, false, INFINITE)
Is there any way to achieve the same effect with std::thread?
To the very best of my knowledge, there is nothing in the standard library that supports a wait of that nature. The standard library is built on top of the underlying operating system threading support. By necessity the standard library can only offer lowest common denominator functionality. Which means that it is not able to wrap some of the richer functionality offered by the Win32 threading library.
Just use a std::condition_variable
and have your threads fire notify_all()
or notify_one()
right before they finish.
Then do cv.wait()
where you want your WaitForMultipleObjects()
call.
Try Async++ Composition which is a reference implementation for the N3428 C++ standard proposal.
This article is relevant before that:
Broken promises–C++0x futures
In an unportable way you can also call std::thread::native_handle() to use WaitForMultipleObjects
with the return.
Here's an example of how you can achieve the same effect using std::thread
and std::future
if you are willing to let the main thread sleep while polling the readiness of the threads (alternatively you could let a dedicated thread handle the waiting).
Consider this function, taking a range of iterators to a container of std::future
, which will block until at least one task is finished:
const int TIME_BETWEEN_POLLS_MS = 50;
// Wait (sleep) between polls until a task is finished then return iterator to future.
template <typename Iterator>
Iterator waitForFirst(Iterator first, Iterator last) {
auto it = first;
auto status = std::future_status::timeout;
while (status != std::future_status::ready) {
if (++it == last) { // Rotate in range.
it = first;
}
status = it->wait_for(std::chrono::milliseconds(TIME_BETWEEN_POLLS_MS));
}
return it;
}
Now if you have a container of futures (std::future
) associated with the return values of your tasks running on separate threads, you can simply use the function waitForFirst
to get an iterator to the future that gets its result first.
// Lets say you have a vector of futures, e.g.
std::vector<std::future<std::thread::id>> futures;
/* Push futures to vector... */
// Block until first task is finished.
// 'it' is iterator to future associated with result.
auto it = waitForFirst(std::begin(futures), std::end(futures));
See live example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With