为什么我不能为一个 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,请动态分配这些内部组件。