2013-10-04 25 views
0

我有一个简单的异步服务器,它受到boost asio documentation(单线程服务器)中的HTTP服务器示例的启发,该服务器处理客户端发送的请求。在升压异步异步服务器中执行计算得分

我的server类每次新客户端连接并调用它的start()方法(如在HTTP服务器示例中)时会创建一个新对象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 
     } 
} 

所有这一切都工作得非常好,:一个connection例如读取客户端的请求,并发送应答之后使用异步操作(即boost::asio::async_readboost::asio::async_write

这里是connection类的简化版本,在某些情况下,我需要执行繁重的计算任务(REQUEST_TYPE_2)。我无法在handle_read_request中执行这些任务,因为它们会阻止单线程服务器并阻止其他客户端开始提供服务。

理想情况下,我想将我繁重的计算任务提交给线程池,并在完成任务时运行我的连接类的方法(例如connection::handle_done_task(std::string computation_result))。这个handle_done_task(std::string computation_result)会将计算结果发送给客户端(使用boost::asio::async_write)。

我该怎么办?是否存在一些我应该注意的问题(从多个线程在同一个套接字上调用boost::asio::async_write是否安全)?

回答

0

由于文件明确规定,ASIO对象(除strand/io_service)不是线程安全的,所以没有同步你不应该从多个线程调用async_write。相反,请使用post-to-io_service成语。像这样:

// 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(); 
}