[英]Boost ASIO blocking callbacks
从asio到阻塞的回调是否安全(或合理)?
void Connection::start() {
/* Assume std::string buffer; that has data to write. */
auto callbackFn = boost::bind(&Connection::callback, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred);
boost::asio::async_write(_socket, boost::asio::buffer(buffer), callBackFn);
}
void Connection::callback(const boost::system::error_code& error,
std::size_t bytesSent) {
/* Perform long running action with bytes sent */
boost::asio::async_write(...);
}
还是应该在回调中生成线程,然后立即返回并在该线程完成后执行操作?
是的,在许多情况下都是合理的。 但是,作为架构师,您有责任确定在您的情况下这是否合理。
一般而言,您的io_service
将在一个线程上运行,即它将在其上调用回调的线程,这意味着它在调用回调时未处理消息。 如果可以的话,那就很好了。 (请注意,这里出现了“安全”部分-您是否正确地保护对象以供跨线程使用?)
如果不正常,则应将消息运送到另一个线程进行处理。
对于我和我的房子,我们更喜欢使用Active Object模式来保持IO服务的响应速度,并将多线程担忧降至最低。 请参阅Herb Sutter的有效并发系列文章。 具体来说,您应该阅读:
PS,如果可能的话,请放弃boost::bind()
以支持C ++ 11/14 lambda。
更新 :至于为什么更喜欢lambda,答案归结为清晰和可维护性(性能大致相同 ,lambda略有优势)。 一旦您习惯了使用lambda语法进行捕获,而后又不怎么做,它就会自然得多。 Bind要求“从内而外”阅读它,从心理上进行解析永远不会变得很自然,并且对于成员函数和捕获引用更加乏味。 考虑(改编自Boost docs ):
struct S
{
void foo( int&, double ) const;
} s;
// ...
auto x = 0;
auto binder = bind( &S::foo, s, ref(x), placeholder::_1 ); // s.foo(x-as-ref, _1)
auto lambda = [&]( auto d ) { s.foo( x, d ); };
auto d = 42.0;
binder( d );
lambda( d );
底部的调用语法是相同的,但lambda定义对于实际发生的事情要清晰得多。 Lambda也可以轻松扩展为多个语句,而bind则不能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.