boost asio 和条件变量——奇怪的输出

Posted

技术标签:

【中文标题】boost asio 和条件变量——奇怪的输出【英文标题】:boost asio and condition variables -- strange output 【发布时间】:2014-04-02 14:46:02 【问题描述】:

建议我有以下代码:

#include <boost/asio/io_service.hpp>
#include <boost/thread.hpp>

#include <condition_variable>
#include <iostream>
#include <mutex>

const int THREAD_POOL_SIZE = 2;

std::condition_variable g_cv;
std::mutex g_cv_mutex;
bool g_answer_ready;

void foo()

  std::cout << "foo \n";
  std::unique_lock<std::mutex> lock(g_cv_mutex);
  g_answer_ready = true;
  g_cv.notify_all();


int main()

  boost::asio::io_service io_service;

  for (int i = 0; i < 10; ++i)
  
    std::auto_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(io_service));

    boost::thread_group threads;
    for (int i = 0; i < THREAD_POOL_SIZE; ++i)
    
      threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
    

    std::unique_lock<std::mutex> lock(g_cv_mutex);

    io_service.post(foo);

    g_answer_ready = false;
    g_cv.wait_for(lock, std::chrono::milliseconds(2000));

    if (!g_answer_ready)
    
      std::cout << "timed_out \n";
    

    io_service.stop();
    threads.join_all();
  

程序启动时的输出会有所不同。例如,

foo
timed_out
foo
foo

但是,如果我在循环内移动 boost::asio::io_service 对象构造,它会按预期工作:

foo
foo
foo
foo
foo
foo
foo
foo
foo
foo

为什么?我究竟做错了什么?我该如何解决?

提升 1.54,MSVC-11.0

【问题讨论】:

【参考方案1】:

如果我理解正确,您需要修复循环中的最后几行(有关说明,请参阅 cmets):

// io_service.stop();
// threads.join_all();

work.reset(); // <- signal to process all pending jobs and quit from io_service::run function
threads.join_all(); // <- wait for all threads
io_service.reset(); // <- now `io_service` can accept new tasks

所以,原来的代码有两个问题:

io_service.stop() 将取消已发布但尚未处理的作业(通常这不是程序员想要的), 需要io_service.reset() 才能将io_service 的状态从“停止”更改为“准备接受新工作”。

【讨论】:

以上是关于boost asio 和条件变量——奇怪的输出的主要内容,如果未能解决你的问题,请参考以下文章

Boost::asio::async_read 不会在条件下停止

boost asio doc中教程的奇怪输出

boost::asio::async_read_until 与自定义匹配条件运算符重载混淆

实现真正 boost::asio::async_read_until 的最简单方法

boost.asio 如何发现我的服务器应用程序正在侦听哪个端口?

Boost asio:无法确认文件传输