链内是什么意思?

时间:2016-06-15 09:20:15

标签: c++ c++11 boost-asio

我目前正试图抓住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 ......这正是我不理解的部分。

2 个答案:

答案 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会为您做一些优化:

  1. 它会检查您是从一个工作线程内部还是从其他某个线程(可能是某个其他dispatch实例)调用它。当它在strand的当前执行上下文之外被调用时,那就是当它被称为io_service时。因此,在outside the strand情况下,当有其他处理程序在队列中等待时,调度将只将outside的处理程序排入队列,或者当它可以保证不会同时调用它时将直接调用它。此队列中可能正在其中一个工作线程中运行的任何其他处理程序。
  2. <强>更新 如评论部分所述,post表示inside,例如:我发布了一个处理程序called within another handler,在该处理程序中,我正在执行另一个处理程序的A。现在,正如在#2中解释的那样,如果没有其他处理程序在strands串行队列中等待,则将同步调用dispatch处理程序。如果不满足此条件,则表示从dispatch调用dispatch

    1. 现在,如果从链的outside调用dispatch,即不在当前执行上下文中,则asio检查其outside以查看其串行队列中是否存在任何其他处理程序运行与否。如果不是,那么它将直接同步调用该处理程序。因此,没有排队处理程序的成本(我认为不会进行额外的分配,但不确定)。
    2. 让我们现在看一下文档链接:

        

      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。如果调用线程正在执行通过truepost()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提供了排序和非并发的保证,这样就不会同时调用f1f2。此外,如果在添加f1之前添加了f2,则会在f1之前调用f2