简体   繁体   English

在Boost Asio异步服务器中执行计算任务

[英]Execute computational taks in boost asio asynchronous server

I have a simple asynchronous server, heavily inspired from the HTTP server example in boost asio documentation (single-threaded server), which processes requests sent by clients. 我有一个简单的异步服务器,其灵感来自boost asio文档 (单线程服务器)中的HTTP服务器示例,该服务器处理客户端发送的请求。

My server class creates a new connection object everytime a new client connects and calls its start() method (as in the HTTP server example). 每当新客户端连接并调用其start()方法(如HTTP服务器示例)时,我的server类都会创建一个新的connection对象。 A connection instance reads the client's request and sends a reply afterwards using asynchronous operations (ie boost::asio::async_read and boost::asio::async_write ) connection实例读取客户端的请求,然后使用异步操作(例如, boost::asio::async_readboost::asio::async_write )发送回复。

Here is a simplified version of the connection class : 这是connection类的简化版本:

void connection::start() {
    // Read request from a client
    boost::asio::mutable_buffers_1 read_buffer = boost::asio::buffer(
            buffer_data_, REQUET_SIZE);
    boost::asio::async_read(socket_, read_buffer,
            boost::bind(&connection::handle_read_request, shared_from_this(),
                    read_buffer, boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred));
}

// Error handling omitted for the sake of brievty
void connection::handle_read_request(boost::asio::mutable_buffers_1& buffer,
    const boost::system::error_code& e, std::size_t bytes_transferred) {
      request req = parse_request(buffer);
      if(req.type_ = REQUEST_TYPE_1) {
          reply rep(...........);
          rep.prepare_buffer(buffer_data_.c_array());
          // Send the request using async_write
          boost::asio::async_write(socket_,
               boost::asio::buffer(buffer_data_, rep.required_buffer_size()),
               boost::bind(&connection::stop, shared_from_this()));
      } else if(req.type_ = REQUEST_TYPE_2 {
          // Need to do heavy computational task
      }
}

All of this works very well, however, in some cases, I need to perform heavy computational tasks ( REQUEST_TYPE_2 ). 所有这些工作都很好,但是在某些情况下,我需要执行繁重的计算任务( REQUEST_TYPE_2 )。 I can't perform these tasks in my handle_read_request because they would block the single-threaded server and prevent other clients from begin served. 我无法在handle_read_request执行这些任务,因为它们会阻止单线程服务器并阻止其他客户端开始服务。

Ideally, I would like to submit my heavy computational task to a thread pool and run a method (eg connection::handle_done_task(std::string computation_result) ) of my connection class on completion of the task. 理想情况下,我想将繁重的计算任务提交到线程池,并在任务完成时运行我的连接类的方法(例如connection::handle_done_task(std::string computation_result) )。 This handle_done_task(std::string computation_result) would send the result of the computation to the client (using boost::asio::async_write ). 这个handle_done_task(std::string computation_result)会将handle_done_task(std::string computation_result)结果发送到客户端(使用boost::asio::async_write )。

How can do I that ? 我该怎么办? Are there some issues I should be aware of (Is it safe to call boost::asio::async_write on the same socket from mutiple threads) ? 我应该注意一些问题吗(从多个线程在同一套接字上调用boost::asio::async_write是否安全)?

As the documentation states explicitly, asio objects (except for strand / io_service ) are not thread-safe, so you shouldn't call async_write from multiple threads without synchronization. 正如文档中明确指出的那样,asio对象( strand / io_service除外)不是线程安全的,因此您不应在没有同步的情况下从多个线程调用async_write Instead, use post-to-io_service idiom. 而是使用post-to-io_service惯用语。 Like this: 像这样:

// pseudocode, untested!
if (req.type_ = REQUEST_TYPE_2) 
{
  auto self = shared_from_this(); // lets capture shared_ptr<connection> to ensure its lifespan
  auto handler = [=](computation_result_type res)
  {
    // post the function that accesses asio i/o objects to `io_service` thread
    self->io_->post([] { handle_done_task(res); });
  }

  thread worker([=](const std::function<(computation_result_type res)> &handler) 
  {     
    // do the heavy work...
    // then invoke the handler
    handler(result);
  });
  worker.detach();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM