WaitForMultipleObjects альтернатива с std:: thread?

Моя проблема в том, что у меня несколько потоков, они хранятся в каком-то контейнере, и мне нужно знать, когда поток в определенной позиции закончен. В окнах я бы сделал что-то вроде:

HANDLE handles[3];
//handles were initialized
DWORD finishingThread = WaitForMultipleObjects(3, handles, false, INFINITE)

Есть ли способ добиться такого же эффекта с помощью std:: thread?

Ответ 1

Насколько я знаю, в стандартной библиотеке нет ничего, что поддерживало бы ожидание такого характера. Стандартная библиотека построена поверх базовой поддержки потоковой поддержки операционной системы. По необходимости стандартная библиотека может предлагать только самые низкие общие функции знаменателя. Это означает, что он не может обернуть некоторые из более богатых функций, предлагаемых библиотекой потоков Win32.

Ответ 2

Просто используйте std::condition_variable и стреляйте в свои потоки notify_all() или notify_one() прямо перед тем, как закончите.

Затем выполните cv.wait(), где вы хотите, чтобы ваш вызов WaitForMultipleObjects().

Ответ 3

Вот пример того, как вы можете добиться такого же эффекта, используя std::thread и std::future, если вы хотите позволить спать основной нить при опросе готовности потоков (в качестве альтернативы вы можете позволить выделенному потоку обрабатывать ожидание).

Рассмотрим эту функцию, взяв ряд итераторов в контейнер std::future, который будет блокироваться, пока не будет завершена по крайней мере одна задача:

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;
}

Теперь, если у вас есть контейнер фьючерсов (std::future), связанный с возвращаемыми значениями ваших задач, запущенных на отдельных потоках, вы можете просто используйте функцию waitForFirst, чтобы получить итератор в будущем, который сначала получит свой результат.

    // 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 = finishingThread(std::begin(futures), std::end(futures));

См. живой пример

Ответ 4

Попробуйте AsynС++ Composition, которая является эталонной реализацией для N3428 Стандартное предложение на С++.

Эта статья имеет отношение до этого:

Broken promises -С++ 0x фьючерсы

Невозможным способом вы можете также вызвать std:: thread:: native_handle(), чтобы использовать WaitForMultipleObjects с возвратом.

Ответ 5

То, что вы хотите, эквивалентно boost:: thread_group.

Не существует, но вы можете написать эту функциональность: std::vector и std:: for_each для вызова join()/WaitForSingleObject для каждого элемента или, конечно, поиск третьей стороны, которая делает то же самое, что и cppthreadpool