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