繁体   English   中英

如何从析构函数(在多线程环境中)正确取消 Boost deadtime_timer?

[英]How do I properly cancel a Boost deadline_timer from a destructor (in a multithreaded environment)?

我有一个名为Timer的 class 公开了两个名为startstop的方法。

void Timer::start() {
    _enabled.store(true, std::memory_order::memory_order_release);
    _timer.expires_from_now(_delay);
    _timer.async_wait(
        std::bind(
            &Timer::tick,
            this,
            std::placeholders::_1
        ));
}

void Timer::stop() {
    _enabled.store(false, std::memory_order::memory_order_release);
    _timer.cancel();
}

void Timer::tick(const boost::system::error_code& error) {
    if (error) return;
    if (!_enabled.load(std::memory_order::memory_order_acquire)) return;
    try {
        _task();
    } catch (...) {}
    if (_enabled.load(std::memory_order::memory_order_acquire)) {
        _timer.expires_from_now(_delay);
        _timer.async_wait(
            std::bind(
                &Timer::tick,
                this,
                std::placeholders::_1
            ));
    }
}

另一个使用Timer实例的 class(处理程序在 ThreadPool 实例中的某个其他线程上执行)在其析构函数中调用stop Boost 文档中,现在可能会调用处理程序并且这两个函数将同时执行,并且处理程序可能会尝试访问已释放的资源。

SomeOtherClass::~SomeOtherClass() {
    _timer.stop();
    // somehow wait for _timer handler to execute
    // delete[] some_thing;
    // other destructive things
}

无论如何要等待处理程序完成执行? 我整天都在摸不着头脑,我对 Boost 很陌生,所以也许我犯了一个设计缺陷。 任何帮助将不胜感激,谢谢。

一种模式是为您的Timer提供一个 shared_ptr (通过使用std::enable_shared_from_this )。

这样,只要处理程序尚未执行,您就可以使计时器保持活动状态(通过保留绑定到处理程序的共享指针的副本)。

其他解决方案可能是:

  • 具有外部分配的计时器(例如,在具有参考稳定性的容器中,例如std::list ),您可以在不再需要它们时手动删除它们
  • 在您自己的线程上运行专用的io_service ,因此您可以join线程以等待io_service上的工作。

根据您的用例/负载模式,一种方法会比其他方法更好。

样品:

我选择了具有一些对比方法的答案(有些不使用 Boost Asio),因此您可以看到权衡取舍以及方法之间的变化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM