0

我正在尝试基于 libtorrent rasterbar 编写自己的 torrent 程序,但在让警报机制正常工作时遇到问题。Libtorrent 提供功能

void set_alert_notify (boost::function<void()> const& fun);

这应该是

该函数的目的是客户端唤醒其主线程,以使用 pop_alerts() 轮询更多警报。如果 notify 函数没有这样做,它将不会被再次调用,直到 pop_alerts 因其他原因被调用。

到目前为止一切顺利,我想我理解了这个功能背后的意图。但是,我的实际实现并没有那么好。到目前为止,我的代码是这样的:

        std::unique_lock<std::mutex> ul(_alert_m);
        session.set_alert_notify([&]() { _alert_cv.notify_one(); });
        while (!_alert_loop_should_stop) {
            if (!session.wait_for_alert(std::chrono::seconds(0))) {
                _alert_cv.wait(ul);
            }
            std::vector<libtorrent::alert*> alerts;
            session.pop_alerts(&alerts);
            for (auto alert : alerts) {
                LTi_ << alert->message();
            }
        }

但是有一个竞争条件。如果wait_for_alert返回NULL(因为还没有警报)但传递给的函数set_alert_notify在之前被调用_alert_cw.wait(ul);,则整个循环将永远等待(因为引用中的第二句)。

目前,我的解决方案只是改变_alert_cv.wait(ul);_alert_cv.wait_for(ul, std::chrono::milliseconds(250));在保持足够低的延迟的同时减少每秒的循环数。

但这确实是比解决方案更多的解决方法,我一直认为必须有适当的方法来处理这个问题。

4

1 回答 1

0

您需要一个变量来记录通知。它应该由拥有条件变量的同一个互斥锁保护。

bool _alert_pending;

session.set_alert_notify([&]() {
    std::lock_guard<std::mutex> lg(_alert_m);
    _alert_pending = true;
    _alert_cv.notify_one();
});
std::unique_lock<std::mutex> ul(_alert_m);
while(!_alert_loop_should_stop) {
    _alert_cv.wait(ul, [&]() {
         return _alert_pending || _alert_loop_should_stop;
    })
    if(_alert_pending) {
        _alert_pending = false;
        ul.unlock();
        session.pop_alerts(...);
        ...
        ul.lock();
    }
}
于 2017-07-09T23:26:45.963 回答