C ++ 11加入完成的第一个线程

时间:2016-01-21 21:27:27

标签: multithreading c++11

有没有办法启动两个(或更多)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()函数。

注意:我需要这个的真正原因是我有两个不同的阻塞函数,我从中接收命令,当它们中的任何一个准备就绪时,我想处理第一个到达的命令并继续到下一个命令已经完成了。 (顺序处理来自两个并行源的命令)

谢谢!

1 个答案:

答案 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,例如,它已完成的工作,或其他任何内容。