链内是什么意思?

What does inside a strand mean?

我目前正在尝试着手处理 boost::asio 股线。这样做,我一直在阅读 "invoking strand post/dispatch inside or outside a strand"。不知何故,我无法弄清楚 inside 一条链与 through 一条链有何不同,因此无法理解调用链函数的概念 链外。

可能是我的拼图中少了一小块。有人可以举例说明如何在链内或链外调用链吗?

到目前为止,我想我所理解的是,通过 发布一些内容 一个链将是

m_strand.post(myfunctor);

m_strand.wrap(myfunctor);
io_svc.post(myfunctor); 

后者是否被认为是对链外 dispatch 的调用(相对于另一个是对链内 post 的调用)? strand 的 "inside realm" 和 strand 操作的线程之间是否存在某种关系?

如果在链中只是为了调用链的功能,那么 strand class's documentation 将毫无意义。它指出 strand::post 可以在链外调用......这正是我不明白的部分。

我什至在理解这个概念时遇到了一些困难,但在我开始研究 libdispatch 后就清楚了。它帮助我更好地映射了 asio 的东西。

现在让我们看看如何理解 strand。将 strand 视为需要执行的 handlers 的串行队列。

现在,这些处理程序在哪里执行?在 worker 个线程中。

这些工作线程是从哪里来的?来自您在创建链时传递的 io_service 对象。 类似于:

asio::strand s(io_serv_obj);

现在,您一定知道,io_service::run 可以由单个线程或多个线程调用。在我们的例子中,调用 io_serv_objrun 方法的线程是该链的工作线程。所以,它可以是单线程的,也可以是多线程的。

回到 strands,当你 post 一个处理程序时,该处理程序 总是 在我们谈到的串行队列中排队。工作线程将一个接一个地从队列中获取处理程序。

现在,当您执行 dispatch 时,asio 会为您做一些优化:

  1. 它会检查您是从工作线程之一还是从其他线程(可能是其他 io_service 实例)调用它。当它在 strand 的当前执行上下文之外被调用时,就是它被调用的时候 outside the strand。因此,在 outside 的情况下,当队列中有其他处理程序在等待时,调度会像 post 一样将处理程序入队,或者在它可以保证不会与并发调用时直接调用它来自该队列的任何其他处理程序当时可能 运行 在其中一个工作线程中。

更新: 如评论部分所述,inside 表示 called within another handler 即例如:我发布了一个处理程序 A 并且在该处理程序中,我正在执行另一个处理程序的 dispatch。现在,正如 #2 中所解释的那样,如果在 strands 串行队列中没有其他处理程序在等待,则将同步调用调度处理程序。如果不满足此条件,则意味着从 outside.

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

现在让我们看看文档 link:

s.dispatch(a) happens-before s.post(b), where the former is performed outside the strand

这意味着,如果 dispatch 是从当前 run 之外的某个地方调用的,或者有其他处理程序已经入队,那么它需要将处理程序入队,它只是不能同步调用它。由于它是一个串行队列,a 将在 b.

之前执行

如果在 ab(按照上述顺序)入队之前,还有另一个调用 s.dispatch(c) 以及 a 和 b,那么 c 将被执行在 ab 之前,但无论如何 b 都不能在 a.

之前执行

希望这能消除您的疑虑。

对于给定的链对象 s,运行 outside s 意味着 s.running_in_this_thread() returns false。如果调用线程正在执行通过 post()dispatch()wrap() 提交给链的处理程序,则此 returns true。否则,它 returns 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
  • 通过 s.post() 添加到链 s 的函数对象 f1,或者当 s.running_in_this_thread() == false
  • s.dispatch()
  • 通过 s.post() 添加到链 s 的函数对象 f2,或者当 s.running_in_this_thread() == false
  • s.dispatch()

那么strand提供了顺序和非并发的保证,使得f1f2不会被并发调用。此外,如果 f1 的添加发生在 f2 的添加之前,那么 f1 将在 f2.

之前被调用