boost :: asio :: io_service ::在多个线程中运行

时间:2014-04-03 01:23:17

标签: c++ boost boost-asio

我试图使用boost :: asio :: io_service来实现ActiveObject,但结果并不完全符合我的预期:

以下是我的代码:

#include    <boost/asio.hpp>
#include    <chrono>
#include    <boost/date_time/posix_time/posix_time.hpp>
#include    <memory>
#include    <thread>
#include    <string>
#include    <functional>
#include    <ctime>
#include    <chrono>

#define SIZE 10 

class ActiveObject
{
  public:
  ActiveObject()
  {
    executionThread_.reset( new std::thread(    [&]{  service_.run();  }  ) );
  }

    virtual ~ActiveObject()
    {
      // execute all unfinished work in case this object is leaving scope.
      service_.poll();
      service_.stop();
      executionThread_->join();
      std::cout << "active object thread exited" << std::endl;
    }

    void doSomething()
    {
      // post request the io_service to invoke someImpl method and return immediately
      service_.post([=]{ someImpl();});
    }

  protected:
    boost::asio::io_service service_;

  private:
    std::shared_ptr<std::thread> executionThread_;

    void someImpl() {
      std::chrono::milliseconds dura( 200 );
      std::this_thread::sleep_for( dura );
      std::cout << "poll thread id: " << std::this_thread::get_id() << std::endl;
    }

};

int main()
{
  std::cout << "main thread id: " << std::this_thread::get_id() << std::endl;

  ActiveObject obj;

  for(int i=0; i < SIZE; ++i) {
    obj.doSomething(); // call is nonblocking
  }

  std::cout <<  "main thread exited " << std::endl;
  return 0;
}

我想要的是在同一个线程上运行boost :: asio :: io_service :: run,但事实并非如此。从打印的日志中,run()也在主线程上运行。下面是打印的日志:

main thread id: 140070853244800
main thread exited 
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070853244800
poll thread id: 140070832256768
poll thread id: 140070853244800
poll thread id: 140070832256768
active object thread exited

对此有何想法?感谢

1 个答案:

答案 0 :(得分:1)

至少在哪里

service_.poll();
service_.stop();

您正在积极地在活动线程上运行服务。

要缓解,您要说

service_.post([&] { service_.poll();});
service_.stop();

然后poll()将是多余的。此出现以解决您的问题:

然而这是一个大问题;

为什么我们甚至打电话给stop()?所有工作完成后,run()才会完成,对吧?事实上, run()可能会在施工期间/之后立即完成。所有工作都将推迟到析构函数中。

但是,如果run()完成,则需要重置服务(),因此实际上无法运行任务(demo live on Coliru !!!)哎呀。这是一个令人讨厌的竞争条件。

要防止run()过早地完成&#34;,请使用work项: Live On Coliru

#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <chrono>
#include <ctime>
#include <functional>
#include <memory>
#include <string>
#include <thread>

#define SIZE 10

class ActiveObject
{
public:
    ActiveObject()
        : service_(),
          work_(boost::asio::io_service::work(service_))
    {
        executionThread_.reset(new std::thread([&] { service_.run(); }));
    }

    virtual ~ActiveObject()
    {
        // execute all unfinished work in case this object is leaving scope.
        work_ = boost::none;
        executionThread_->join();
        std::cout << "active object thread exited" << std::endl;
    }

    void doSomething()
    {
        // post request the io_service to invoke someImpl method and return immediately
        service_.post([this] { someImpl();});
    }

protected:
    boost::asio::io_service service_;
    boost::optional<boost::asio::io_service::work> work_;

private:
    std::shared_ptr<std::thread> executionThread_;

    void someImpl()
    {
        std::chrono::milliseconds dura(200);
        std::this_thread::sleep_for(dura);
        std::cout << "poll thread id: " << std::this_thread::get_id() << std::endl;
    }

};

int main()
{
    std::cout << "main thread id: " << std::this_thread::get_id() << std::endl;

    ActiveObject obj;
    std::chrono::milliseconds dura(200);
    std::this_thread::sleep_for(dura);

    for(int i=0; i < SIZE; ++i)
    {
        obj.doSomething(); // call is nonblocking
    }

    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout <<  "main thread exited " << std::endl;
}

输出:

main thread id: 140312603891520
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
main thread exited 
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
poll thread id: 140312580617984
active object thread exited