非阻塞 io_service::run

Posted

技术标签:

【中文标题】非阻塞 io_service::run【英文标题】:Nonblocking io_service::run 【发布时间】:2018-09-01 08:33:53 【问题描述】:

我正在尝试实现一个包含两个处理循环的 C++ 应用程序。目前,第一个处理循环(boost 的 io_service::run)阻止了第二个处理循环的执行。

使用线程或 std::async 方法的方法失败。 (我没有多线程方面的经验/背景)。

是否有一种优雅的方式可以在另一个线程中运行 io_service::run,同时仍对传入的 UDP 数据报执行回调?

主文件:

class Foo

public:
    Foo();

    void callback(const int&);
private:
    // ... (hopefully) non-relevant stuff...
;

int main()


  Foo foo_obj;

  // I need to run this function (blocking) but the constructor is blocking (io_server::run())
  run();

  return 0;



Foo::Foo()
    boost::asio::io_service io;

    UDP_Server UDP_Server(io);

    // Set function to be called on received message
    UDP_Server.add_handler(std::bind(&Foo::callback, this, std::placeholders::_1));

    // This function should be non-blocking
    // -> tried several things, like threads, async, ... (unfortunately not successful)
    io.run();


// realization of callback function here (see class definition)

包含自定义“库”:

class UDP_Server

public:
    UDP_Server(boost::asio::io_service&);

    void add_handler(std::function<void(int)>);

private:
    // Function handle
    std::function<void(int)> callbackFunctionHandle;

    // Functions
    void start_receive();
    void handle_receive(const boost::system::error_code&, std::size_t);

    // ... (hopefully) non-relevant stuff...
;

// Constructor
UDP_Server::UDP_Server(boost::asio::io_service& io_service)
    : socket_(io_service, udp::endpoint(udp::v4(), UDP_PORT))



// Store a callback function (class foo) to be called whenever a message is received
void UDP_Server::add_handler(std::function<void(int)>  callbackFunction)
    try
    
        callbackFunctionHandle = callbackFunction;
        start_receive();
    
    catch (std::exception& e)
    
        std::cerr << e.what() << std::endl;
    


// Async receive
UDP_Server::start_receive()

  socket_.async_receive_from(
      boost::asio::buffer(recv_buffer_), remote_endpoint_,
      boost::bind(&UDP_Server::handle_receive, this,
        boost::asio::placeholders::error,
        boost::asio::placeholders::bytes_transferred));


// When message is received
void UDP_Server::handle_receive(const boost::system::error_code& error,
std::size_t bytes_transferred)

  if (!error || error == boost::asio::error::message_size)
  

    // ... do smth. with the received data ...

    // Call specified function in Foo class
    callbackFunctionHandle(some_integer);

    start_receive();

else
  // ... handle errors



【问题讨论】:

是什么阻止您使用单个io_service 我使用的是单个io_service另一个阻塞函数(由单个run()表示)是一个与ROS相关的ros::spin() boost.org/doc/libs/1_42_0/doc/html/boost_asio/reference/… 感谢您的参考。我还看了run_one()。问题是我经常通过 UDP 接收消息,应该尽快处理。所以,我应该坚持run(),对吧? 【参考方案1】:

看看他们在here做了什么:

boost::asio::io_service io_service;
/** your code here **/
boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
ros::spin();

因此,您基本上在与 ros::spin() 不同的线程中启动对 io_service::run() 的阻塞调用。

如果你启动绑定到单个 cpu 节点(为了不浪费 2 个 cpu 节点等待命令)你的调度程序可能会处理一些事情。

【讨论】:

我收到Bus error: 10 代码错误,我不知道为什么。

以上是关于非阻塞 io_service::run的主要内容,如果未能解决你的问题,请参考以下文章

阻塞赋值和非阻塞赋值有何区别

IO阻塞非阻塞同步异步同步阻塞同步非阻塞异步阻塞异步非阻塞

verilog 阻塞和非阻塞啥区别啊?

非阻塞socket总结

同步阻塞同步非阻塞异步阻塞异步非阻塞--简明介绍

并行,并发,串行,同步,异步,阻塞,非阻塞,同步阻塞,同步非阻塞,异步阻塞,异步非阻塞