为什么我们需要在asico教程Timer.5示例中的主线程和新线程"t"中都运行"io.r



参考:tuttimer5

coliru演示

根据教程,主要功能如下:

int main()
{
boost::asio::io_context io;
printer p(io);
boost::thread t(boost::bind(&boost::asio::io_context::run, &io));
io.run(); // Why do we need to call io.run() here?
t.join();
return 0;
}

我想了解为什么我们需要在主函数中有两个io.run();。这是我的测试结果:

测试1(在主函数的主线程中调用io.run(((:

main-Thread #32
printer-Thread #32
print1-Thread #32
Timer 1: 0
print2-Thread #32
Timer 2: 1
print1-Thread #32
Timer 1: 2
print2-Thread #32
Timer 2: 3
print1-Thread #32
Timer 1: 4
print2-Thread #32
Timer 2: 5
print1-Thread #32
Timer 1: 6
print2-Thread #32
Timer 2: 7
print1-Thread #32
Timer 1: 8
print2-Thread #32
Timer 2: 9
~printer-Thread #32
Final count is 10

Observation1:print1print2都由主线程调用。

测试2(不在主函数的主线程中调用io.run(((:

main-Thread #40
printer-Thread #40
print1-Thread #29
Timer 1: 0
print2-Thread #29
Timer 2: 1
print1-Thread #29
Timer 1: 2
print2-Thread #29
Timer 2: 3
print1-Thread #29
Timer 1: 4
print2-Thread #29
Timer 2: 5
print1-Thread #29
Timer 1: 6
print2-Thread #29
Timer 2: 7
print1-Thread #29
Timer 1: 8
print2-Thread #29
Timer 2: 9
~printer-Thread #40
Final count is 10

Observation2:print1print2都不被主线程调用。

注意:测试结果来自我的本地linux盒子(g++(Ubuntu 11.1.0-1ubuntu1~18.04.1(11.1.0(。结果看起来与coliru有点不同。

在这种情况下,io_context的操作就像一个经典的线程池。然而,异步任务是在操作系统端的某个地方执行的在io_context::运行的线程上调用完成处理程序函数正在运行。更准确地说:每个完成处理程序在io_context::run函数所在的第一个空闲线程上调用正在运行。

问题>我们想在主线程和原始教程中的新线程中调用io.run);的主要原因是什么?

谢谢

这些都不是必需的。它只显示了任务分布在所有参与运行/轮询执行上下文的线程上。

从这个意义上说,编写的代码只是让2个线程运行io上下文的最便宜的方法。在最近的Boost版本中,有人可能会说thread_pool是更干净的代码,但会产生3个线程(计算主线程(:

int main()
{
report("main") << std::endl;
boost::asio::thread_pool io(2);
printer p(io.get_executor());
io.join();
}

在Coliru上直播

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iomanip>
#include <iostream>
#include <thread>
namespace asio = boost::asio;
std::ostream& report(const std::string& suffix_msg)
{
auto tid = std::hash<std::thread::id>{}(std::this_thread::get_id()) % 100;
return std::cout << suffix_msg << "-Thread #" << std::setw(2)
<< std::setfill('0') << tid;
}
class printer {
public:
printer(asio::any_io_executor ex)
: strand_(asio::make_strand(ex))
, count_(0)
{
report("printer") << std::endl;
timer1_.async_wait(
std::bind(&printer::print_callback, this, "Timer 1", std::ref(timer1_)));
timer2_.async_wait(
std::bind(&printer::print_callback, this, "Timer 2", std::ref(timer2_)));
}
~printer()
{
report("~printer") << "tFinal count is " << count_ << std::endl;
}
void print_callback(std::string_view name, asio::steady_timer& timer)
{
if (count_ < 10) {
report("print_callback") << "t" << name << ": " << count_ << std::endl;
++count_;
timer.expires_at(timer.expiry() + asio::chrono::seconds(1));
timer.async_wait(std::bind(&printer::print_callback, this, name,
std::ref(timer)));
}
}
private:
asio::any_io_executor strand_;
int                   count_ = 0;
asio::steady_timer    timer1_{strand_, asio::chrono::seconds(1)};
asio::steady_timer    timer2_{strand_, asio::chrono::seconds(1)};
};
int main()
{
report("main") << std::endl;
boost::asio::thread_pool io(2);
printer p(io.get_executor());
io.join();
}

打印,例如

main-Thread #59
printer-Thread #59
print_callback-Thread #06   Timer 1: 0
print_callback-Thread #06   Timer 2: 1
print_callback-Thread #74   Timer 1: 2
print_callback-Thread #74   Timer 2: 3
print_callback-Thread #74   Timer 1: 4
print_callback-Thread #74   Timer 2: 5
print_callback-Thread #74   Timer 1: 6
print_callback-Thread #74   Timer 2: 7
print_callback-Thread #74   Timer 1: 8
print_callback-Thread #74   Timer 2: 9
~printer-Thread #59 Final count is 10

最新更新