有没有办法启动两个(或更多)C ++ 11线程并加入()第一个完成的线程?
示例场景:
#include <iostream>
#include <thread>
using namespace std;
void prepare_item1() {std::cout << "Preparing 1" << std::endl;}
void consume_item1() {std::cout << "Consuming 1" << std::endl;}
void prepare_item2() {std::cout << "Preparing 2" << std::endl;}
void consume_item2() {std::cout << "Consuming 2" << std::endl;}
int main()
{
std::thread t1(prepare_item1);
std::thread t2(prepare_item2);
t1.join();
consume_item1();
t2.join();
consume_item2();
return 0;
}
我本来喜欢做那样的事情:
int main()
{
std::thread t1(prepare_item1);
std::thread t2(prepare_item2);
finished_id=join_any(t1,t2)
if (finished_id==1)
{
consume_item1();
...
}
else if (finished_id==2)
{
consume_item2();
...
}
return 0;
}
另外,我希望解决方案是阻塞的,类似于t.join()函数。
注意:我需要这个的真正原因是我有两个不同的阻塞函数,我从中接收命令,当它们中的任何一个准备就绪时,我想处理第一个到达的命令并继续到下一个命令已经完成了。 (顺序处理来自两个并行源的命令)
谢谢!
答案 0 :(得分:2)
这是一个线程安全的多生产者多用户队列:
template<class T>
struct safe_queue {
std::deque<T> data;
std::atomic<bool> abort_flag = false;
std::mutex guard;
std::condition_variable signal;
template<class...Args>
void send( Args&&...args ) {
{
std::unique_lock<std::mutex> l(guard);
data.emplace_back(std::forward<Args>(args)...);
}
signal.notify_one();
}
void abort() {
abort_flag = true; // 1a
{ std::unique_lock<std::mutex>{guard}; }
signal.notify_all(); // 1b
}
std::experimental::optional<T> get() {
std::unique_lock<std::mutex> l(guard);
signal.wait( l, [this]()->bool{ // 2b
return !data.empty() || abort_flag.load(); // 2c
});
if (abort_flag.load()) return {};
T retval = std::move(data.front());
data.pop_front();
return retval;
}
};
让线程将数据推入队列,主线程在其上执行.get()
。
如果调用了abort()
,则所有等待的线程都被唤醒,并且#34;空&#34;价值来自.get()
。
它使用std::experimental::optional
,但您可以用其他东西替换它(抛弃中止?无论如何)。
代码略微修改自this other answer。请注意,我认为其他答案中存在一些错误,我在上面进行了更正,并尝试解决其他问题。
您发送的消息可能是准备等待的线程的ID,例如,它已完成的工作,或其他任何内容。