在第 5 篇教程中,我在问题底部给出的代码,asio 文档介绍了输出如下:
Timer 2: 0
Timer 1: 1
Timer 2: 2
Timer 1: 3
Timer 2: 4
.
.
.
在第一个之后,它是可以预期的,具有顺序。
但是即使 Timer1 首先被包裹在 strand 中,为什么 Timer 2 先开始运行?
#include <iostream>
#include <asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer
{
public:
printer(asio::io_service& io)
: strand_(io),
timer1_(io, boost::posix_time::seconds(1)),
timer2_(io, boost::posix_time::seconds(1)),
count_(0)
{
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
}
~printer()
{
std::cout << "Final count is " << count_ << "\n";
}
void print1()
{
if (count_ < 10)
{
std::cout << "Timer 1: " << count_ << "\n";
++count_;
timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
}
}
void print2()
{
if (count_ < 10)
{
std::cout << "Timer 2: " << count_ << "\n";
++count_;
timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
}
}
private:
asio::strand strand_;
asio::deadline_timer timer1_;
asio::deadline_timer timer2_;
int count_;
};
int main()
{
asio::io_service io;
printer p(io);
asio::thread t(boost::bind(&asio::io_service::run, &io));
io.run();
t.join();
system("PAUSE");
return 0;
}
最佳答案
一个 strand
用于提供处理程序的串行执行。此外,在某些条件下,它为通过链发布或分派(dispatch)的处理程序的调用顺序提供保证。该示例不满足这些条件。此外,不能保证会观察到完成处理程序之间的交替模式。
IO 对象,例如计时器,不被链包裹,完成处理程序是。一个 strand
可以被认为与处理程序的 FIFO 队列相关联。如果处理程序队列当前没有处理程序发布到 io_service
,然后它会从自身弹出一个处理程序并将其发布到相关的io_service
.此流程保证不会同时调用发布到同一链中的处理程序。
strand.post()
将处理程序排入链中。 strand.dispatch()
如果当前调用者正在链的上下文中运行,则将运行处理程序。否则,它将像 post()
一样将处理程序排入队列。 . strand.wrap()
返回一个新的完成处理程序,当它被调用时,将 dispatch()
包裹的处理程序进入链。本质上,wrap()
将处理程序的分派(dispatch)延迟到链中。 给定完成处理程序
a
和 b
, 如果 a
在 b
之前入队,然后 a
将在 b
之前调用.这是所有场景都可以减少的根本保证。 a
的场景在 b
之前保证是 documented如下:strand.post(a)
发生在 strand.post(b)
之前.如post()
不尝试调用 post()
内提供的处理程序, a
在 b
之前入队. strand.post(a)
发生在 strand.dispatch(b)
之前, 其中 strand.dispatch(b)
在链之外执行。如strand.dispatch(b)
出现在链之外,b
就像 post()
一样排队.因此,这减少到 strand.post(a)
发生在 strand.post(b)
之前. strand.dispatch(a)
发生在 strand.post(b)
之前, 其中 strand.dispatch(a)
发生在链之外。如strand.dispatch(a)
出现在链之外,a
就像 post()
一样排队.因此,这减少到 strand.post(a)
发生在 strand.post(b)
之前. strand.dispatch(a)
发生在 strand.dispatch(b)
之前,两者都在链之外执行。由于都没有出现在一个链中,所以两个处理程序都像 post()
一样排队。 .因此,这减少到 strand.post(a)
发生在 strand.post(b)
之前. io_service
makes no guarantees关于处理程序的调用顺序。此外,从 strand.wrap()
返回的处理程序不在一个链的上下文中运行。示例代码简化为:auto wrapped_print1 = strand.wrap(&print1);
auto wrapped_print2 = strand.wrap(&print2);
timer1_.async_wait(wrapped_print1);
timer2_.async_wait(wrapped_print2);
如果
async_wait
操作同时完成,wrapped_print1
和 wrapped_print2
完成处理程序将发布到 io_service
用于延迟调用。作为 io_service
不保证调用顺序,可以选择调用wrapped_print1
首先,或者它可以选择调用 wrapped_print2
第一的。两个wrapped_print
在链的上下文之外以未指定的顺序调用处理程序,导致 print1()
和 print2()
以未指定的顺序排入链中。wrapped_print
的未指定顺序被调用是为什么不能保证观察到 print1
之间的交替模式。和 print2
原始示例中的处理程序。然而,鉴于 io_service
的当前实现的内部调度程序,人们会观察到这样的模式。
关于c++ - boost asio doc中教程的奇怪输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28010880/