我是 boost::asio 的新手。 boost doc说:
The strand object guarantees that handlers posted or dispatched through the strand will not be executed concurrently. The handler may be executed inside this function if the guarantee can be met. If this function is called from within a handler that was posted or dispatched through the same strand, then the new handler will be executed immediately.
所以我想知道新的处理程序何时会立即执行,为什么不直接调用它而不是使用dispatch?
最佳答案
如果调用者始终在链中运行,则可以直接调用处理程序。否则,如果调用者并不总是在链中运行,则可以使用 strand.dispatch()
来满足并发要求,同时可能优化某些调用链。
例如,考虑应用程序协议(protocol)要求定期发送心跳并响应每个心跳请求的情况。人们可以设计异步调用链,以便有两个离散的调用链:
keepalive
类负责定期发送心跳的调用链。它将设置一个计时器到期,到期后,设置新的到期时间并发送心跳:.---------------------------. V | keepalive::start_timer() | { | timer_.expires_from_now(...); | timer_.async_wait( | [this](...) | { | this->start_timer(); -----' io.send_headerbeat(); }); } keepalive.start_timer();
io
类管理套接字,使用私有(private)链来序列化对套接字的访问。io
类将从套接字读取并处理读取的数据。.-------------------------------------. V | io::read_data() | { | async_read(socket_, buffer_, | strand_.wrap([this](...) | { | auto message = parse(buffer_); | this->read_data(); ----------------' if (is_heartbeat_request(message)) { this->send_heartbeat(); } })); } io::start() { strand_.post([this]{ this->read_data(); }); }
在 keepalive
的调用链中,io::send_heartbeat()
是从 io
的私有(private)链外部调用的,keepalive
无权访问。另一方面,在 io 的调用链中,io::send_heartbeat() 是从链内部调用的。如果 io::send_heartbeat() 调度将在套接字上启动写入操作的处理程序,那么它将与两个异步调用链一起正常且透明地工作。此外,当在 io 调用链中调用时,处理程序会立即执行,从而避免了发布和与链同步的开销。
io::send_heartbeat()
{
strand_.dispatch(
[this]()
{
async_write(this->socket_, ...,
this->strand_.wrap(...));
});
}
strand::dispatch()
如果出现以下情况,将立即在当前线程中执行处理程序:
-
strand::running_in_this_thread()
返回true
strand::running_in_this_thread()
返回false
并且调用者正在运行io_service
并且 strand 指定的处理程序调用顺序可以是遇见
没有公共(public) API 可以确定第二种情况的所有条件。因此,无法确定直接调用处理程序是否安全,而必须使用 strand::dispatch()
。
关于c++ - boost::asio::strand::dispatch(handle) 还是直接调用句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38136537/