非阻塞io_service :: run

时间:2018-03-22 19:04:50

标签: c++ multithreading asynchronous blocking nonblocking

我试图实现一个C ++应用程序,该应用程序包含两个处理循环。目前第一个处理循环(boost' so_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
}

}

1 个答案:

答案 0 :(得分:0)

看看他们在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节点(为了不浪费两个等待命令的cpu节点),您的调度程序可能会处理这些事情。