boost.asio组成的操作成串运行 [英] boost.asio composed operation run in strand

查看:86
本文介绍了boost.asio组成的操作成串运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码:

在线程1中:

boost::async_read(socket, buffer, strand.wrap(read_handler));

在线程2中:

strand.post([](){socket.async_write_some(buffer, strand.wrap(write_handler))});

很明显, read_handler async_write_some write_handler 受链保护,它们不会并发.但是,async_read是一个组合操作,它将对async_read_some调用零次或多次,那些async_read_some也需要受链保护,否则它们可能与线程2中的async_write_some并发.

It is clear that read_handler, async_write_some, write_handler protected by strand, they will not concurrent. However, async_read is an composed operation, it will call zero or more times to async_read_some, those async_read_some also need protect by strand or else they might concurrent with async_write_some in thread 2.

但是从代码来看,strand只包装了 read_handler ,asio如何使所有中间操作(async_read_some)也被strand包裹?

But from the code, strand only wrap read_handler, how asio make all intermediate operations(async_read_some) also wrapped by the strand?

推荐答案

简而言之,返回strand.wrap() 具有与之关联的自定义asio_handler_invoke策略,该策略会将处理程序分派到包装初始处理程序的链中.从概念上讲,它如下:

In short, asio_handler_invoke enables one to customize the invocation of handlers in the context of a different handler. In this case, the object returned from strand.wrap() has a custom asio_handler_invoke strategy associated with it that will dispatch handlers into the strand that wrapped the initial handler. Conceptually, it is as follows:

template <typename Handler>
struct strand_handler
{
  void operator()();
  Handler handler_;
  boost::asio::strand dispatcher_;
};

// Customize invocation of Function within context of custom_handler.
template <typename Function>
void asio_handler_invoke(Function function, strand_handler* context)
{
  context->dispatcher_.dispatch(function);
}

strand_handler wrapped_completion_handler = strand.wrap(completion_handler);
using boost::asio::asio_handler_invoke;
asio_handler_invoke(intermediate_handler, &wrapped_completion_handler);

自定义asio_handler_invoke挂钩可通过依赖于参数的查找找到. 处理程序要求:

The custom asio_handler_invoke hook is located via argument-dependent lookup. This detail is documented in the Handler requirement:

使函数对象f就像通过调用f()一样被执行.

Causes the function object f to be executed as if by calling f().

asio_handler_invoke()函数是使用依赖于参数的查找来定位的.如果没有用户提供的功能,则功能boost::asio::asio_handler_invoke()作为默认功能.

The asio_handler_invoke() function is located using argument-dependent lookup. The function boost::asio::asio_handler_invoke() serves as a default if no user-supplied function is available.

有关asio_handler_invoke的更多详细信息,请考虑阅读答案.

For more details on asio_handler_invoke, consider reading this answer.

请注意,在启动函数中可能会尝试执行 .该文档特别指出,将在与最终完成处理程序相同的上下文中调用中间的处理程序.因此,给出:

Be aware that an operation may be attempted within the initiating function. The documentation is specific that intermediate handlers will be invoked within the same context as the final completion handler. Therefore, given:

assert(strand.running_in_this_thread());
boost::async_read(socket, buffer, strand.wrap(read_handler));

boost::async_read本身必须在strand的上下文中被调用以具有线程安全性.请参阅答案,以获取有关线程安全性和线束的更多详细信息.

the boost::async_read itself must be invoked within the context of strand to be thread-safe. See this answer for more details on thread-safety and strands.

这篇关于boost.asio组成的操作成串运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆