参考: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:print1
和print2
都由主线程调用。
测试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:print1
和print2
都不被主线程调用。
注意:测试结果来自我的本地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