我目前正试图抓住boost::asio
股。这样做,我继续阅读“在内部调用链post/dispatch
或在外部调用链”。不知怎的,我无法弄清楚里面一条链是如何区别于到一条链,因此无法掌握在外面调用一个strand函数的概念总而言之。
可能我的谜题中只有一小块缺失。有人可以举个例子来说明对一个链的调用是在内部还是外部?
我认为到目前为止我所理解的是发布通过一条链的东西
m_strand.post(myfunctor);
或
m_strand.wrap(myfunctor);
io_svc.post(myfunctor);
后者是否被认为是对{}之外的dispatch
的调用(而不是另一个是对post
内部的调用)?链的“内部领域”与链操作的线程之间是否存在某种关系?
如果在一条链中仅仅意味着调用一个链的函数,那么strand
class's documentation将毫无意义。它声明可以在链外调用strand::post
......这正是我不理解的部分。
答案 0 :(得分:9)
即使我在理解这个概念时遇到了一些麻烦,但是一旦我开始研究libdispatch
,我就会变得清晰。它帮助我更好地映射asio
。
现在让我们看看如何从strand
中了解一下。将strand
视为需要执行的handlers
的串行队列。
现在,这些处理程序在哪里执行?在worker
个帖子中。
这些工作线程来自哪里?从创建链时传递的io_service
对象开始。
类似的东西:
asio::strand s(io_serv_obj);
现在,正如您必须知道的那样,io_service::run
可以由单个线程或多个线程调用。在我们的例子中,调用run
的{{1}}方法的线程是该链的工作线程。因此,它可以是单线程或多线程。
回到strands,当你io_serv_obj
一个处理程序时,该处理程序总是在我们谈到的串行队列中排队。工作线程将一个接一个地从队列中获取处理程序。
现在,当您执行post
时,asio会为您做一些优化:
dispatch
实例)调用它。当它在strand的当前执行上下文之外被调用时,那就是当它被称为io_service
时。因此,在outside the strand
情况下,当有其他处理程序在队列中等待时,调度将只将outside
的处理程序排入队列,或者当它可以保证不会同时调用它时将直接调用它。此队列中可能正在其中一个工作线程中运行的任何其他处理程序。 <强>更新强>
如评论部分所述,post
表示inside
,例如:我发布了一个处理程序called within another handler
,在该处理程序中,我正在执行另一个处理程序的A
。现在,正如在#2中解释的那样,如果没有其他处理程序在strands串行队列中等待,则将同步调用dispatch处理程序。如果不满足此条件,则表示从dispatch
调用dispatch
。
outside
调用dispatch
,即不在当前执行上下文中,则asio检查其outside
以查看其串行队列中是否存在任何其他处理程序运行与否。如果不是,那么它将直接同步调用该处理程序。因此,没有排队处理程序的成本(我认为不会进行额外的分配,但不确定)。让我们现在看一下文档链接:
s.dispatch(a)发生在s.post(b)之前,执行前者 在外面
这意味着,如果从当前callstack
之外的某些人调用dispatch
或者已经排队的其他处理程序,那么它需要将处理程序排队,它不能同步调用它。由于它是一个串行队列,run
将在a
之前执行。
如果有另一个电话b
连同a和b,但在s.dispatch(c)
和a
(按照上述顺序)排队之前,b
将在c
之前执行{ {1}}和a
,但b
之前无法执行b
。
希望这可以解除你的怀疑。
答案 1 :(得分:2)
对于给定的链对象s
,在 s
之外运行意味着s.running_in_this_thread()
返回false
。如果调用线程正在执行通过true
,post()
或dispatch()
提交给链的处理程序,则返回wrap()
。否则,它返回false
:
io_service.post(handler); // handler will run outside of strand
strand.post(handler); // handler will run inside of strand
strand.dispatch(handler); // handler will run inside of strand
io_service.post(strand.wrap(handler)); // handler will run inside of strand
假设:
s
f1
添加到s
链的函数对象s.post()
,或s.dispatch()
s.running_in_this_thread() == false
f2
添加到s
链的函数对象s.post()
,或s.dispatch()
s.running_in_this_thread() == false
然后,strand提供了排序和非并发的保证,这样就不会同时调用f1
和f2
。此外,如果在添加f1
之前添加了f2
,则会在f1
之前调用f2
。