简体   繁体   English

使用set_alert_notify唤醒主线程的正确方法是什么?

[英]What's a proper way to use set_alert_notify to wake up main thread?

I'm trying to write my own torrent program based on libtorrent rasterbar and I'm having problems getting the alert mechanism working correctly. 我试图基于libtorrent rasterbar编写自己的torrent程序,但是在使警报机制正常工作时遇到了问题。 Libtorrent offers function Libtorrent提供功能

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

which is supposed to 这应该

The intention of of the function is that the client wakes up its main thread, to poll for more alerts using pop_alerts(). 该功能的目的是客户端唤醒其主线程,以使用pop_alerts()轮询更多警报。 If the notify function fails to do so, it won't be called again, until pop_alerts is called for some other reason. 如果notify函数失败,则不会再次调用它,直到由于其他原因调用pop_alerts为止。

so far so good, I think I understand the intention behind this function. 到目前为止一切顺利,我想我已经理解了此功能的意图。 However, my actual implementation doesn't work so good. 但是,我的实际实现效果不佳。 My code so far is like this: 到目前为止,我的代码是这样的:

        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();
            }
        }

however there is a race condition. 但是有比赛条件。 If wait_for_alert returns NULL (since no alerts yet) but the function passed to set_alert_notify is called before _alert_cw.wait(ul); 如果wait_for_alert返回NULL (因为还没有警报),但是传递给set_alert_notify的函数在_alert_cw.wait(ul);之前_alert_cw.wait(ul); , the whole loop waits forever (because of second sentence from the quote). ,整个循环将永远等待(因为引号中的第二句话)。

For the moment my solution is just changing _alert_cv.wait(ul); 目前,我的解决方案是更改_alert_cv.wait(ul); to _alert_cv.wait_for(ul, std::chrono::milliseconds(250)); _alert_cv.wait_for(ul, std::chrono::milliseconds(250)); which reduces number of loops per second enough while keeping latency low enough. 这样可以充分减少每秒的循环数,同时将等待时间保持在足够低的水平。

But it's really more workaround then solution and I keep thinking there must be proper way to handle this. 但这实际上是比解决方案更多的解决方法,我一直认为必须有适当的方法来解决此问题。

You need a variable to record the notification. 您需要一个变量来记录通知。 It should be protected by the same mutex that owns the condition variable. 它应该由拥有条件变量的同一个互斥锁保护。

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();
    }
}

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

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