为什么我不能为一个 asio io_service 使用两个计时器?
Why can't I use two timers for one asio io_service?
我是 asio 的新手,我正在尝试修改一些示例以达到我的目的。一种想法是 运行 多个计时器,如果我在多个线程上 运行 io_service.run() ,看看行为是否改变。但是,由于多个计时器会导致我不理解的分段错误,我什至没有做到这一点。
我的最小工作示例是这样的:
#include <iostream>
#include <asio.hpp>
class printer {
public:
asio::steady_timer timer;
asio::io_service &io_service;
int count;
printer(asio::io_service &io_service) : io_service(io_service), timer(io_service, asio::chrono::milliseconds(10)) , count(0) {
timer.async_wait(std::bind(&printer::timer_func, this));
}
void timer_func() {
std::cout << "count " << ++count << ", on thread " << std::this_thread::get_id() << std::endl;
if (count < 5)
{
timer.expires_at(timer.expiry() + asio::chrono::milliseconds(10));
timer.async_wait(std::bind(&printer::timer_func, this));
}
}
};
int main()
{
const int NUM_PRINTERS = 2;
asio::io_service io;
std::vector<printer> work_timers;
for (int i = 0; i < NUM_PRINTERS; ++i) {
work_timers.emplace_back(io);
}
io.run();
std::cout << "broker completed.\n";
return 0;
}
对于NUM_PRINTERS=1,这很成功:
count 1, on thread 139779481040704
count 2, on thread 139779481040704
count 3, on thread 139779481040704
count 4, on thread 139779481040704
count 5, on thread 139779481040704
broker completed.
但是,对于 NUM_PRINTERS > 1,我得到一个分段错误:
count 1, on thread 140493102753600
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
从我的角度来看,我不知道这是怎么发生的。两个打印机对象都有自己的变量,我不明白这是从哪里来的。为什么会出现分段错误?
在构造函数中,您将可调用对象绑定到 this
。然而,printer
实例可能会在插入时重新分配 work_timers
时四处移动,从而使 steady_timer
的已注册回调无效。一个简单的解决方法是预先调用 work_timers.reserve(NUM_PRINTERS)
。然后 works(修复警告)。
除了指针失效的未定义行为外,steady_timer
也是 cancelled upon moving,因此尝试调用处理程序失败。你真的应该确保计时器和它们的回调超过延迟。如果您想要更灵活的 printer
class,请动态分配这些内部组件。
我是 asio 的新手,我正在尝试修改一些示例以达到我的目的。一种想法是 运行 多个计时器,如果我在多个线程上 运行 io_service.run() ,看看行为是否改变。但是,由于多个计时器会导致我不理解的分段错误,我什至没有做到这一点。
我的最小工作示例是这样的:
#include <iostream>
#include <asio.hpp>
class printer {
public:
asio::steady_timer timer;
asio::io_service &io_service;
int count;
printer(asio::io_service &io_service) : io_service(io_service), timer(io_service, asio::chrono::milliseconds(10)) , count(0) {
timer.async_wait(std::bind(&printer::timer_func, this));
}
void timer_func() {
std::cout << "count " << ++count << ", on thread " << std::this_thread::get_id() << std::endl;
if (count < 5)
{
timer.expires_at(timer.expiry() + asio::chrono::milliseconds(10));
timer.async_wait(std::bind(&printer::timer_func, this));
}
}
};
int main()
{
const int NUM_PRINTERS = 2;
asio::io_service io;
std::vector<printer> work_timers;
for (int i = 0; i < NUM_PRINTERS; ++i) {
work_timers.emplace_back(io);
}
io.run();
std::cout << "broker completed.\n";
return 0;
}
对于NUM_PRINTERS=1,这很成功:
count 1, on thread 139779481040704
count 2, on thread 139779481040704
count 3, on thread 139779481040704
count 4, on thread 139779481040704
count 5, on thread 139779481040704
broker completed.
但是,对于 NUM_PRINTERS > 1,我得到一个分段错误:
count 1, on thread 140493102753600
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
从我的角度来看,我不知道这是怎么发生的。两个打印机对象都有自己的变量,我不明白这是从哪里来的。为什么会出现分段错误?
在构造函数中,您将可调用对象绑定到 this
。然而,printer
实例可能会在插入时重新分配 work_timers
时四处移动,从而使 steady_timer
的已注册回调无效。一个简单的解决方法是预先调用 work_timers.reserve(NUM_PRINTERS)
。然后 works(修复警告)。
除了指针失效的未定义行为外,steady_timer
也是 cancelled upon moving,因此尝试调用处理程序失败。你真的应该确保计时器和它们的回调超过延迟。如果您想要更灵活的 printer
class,请动态分配这些内部组件。