美文网首页
【Poco笔记】Event——mutex和conditional

【Poco笔记】Event——mutex和conditional

作者: 安安爸Chris | 来源:发表于2018-10-18 17:22 被阅读0次

    Poco中的Event,是对C++11中mutex和conditional_variable做了一层封装,是它具有“Event”的概念。

    Event应该有信号量机制,具有等待信号和set信号的行为。

    所以看Poco的源码,可以看到对应的接口实现。

    Event的内部成员:

    private:
        Event(const Event&);
        Event& operator = (const Event&);
    
        bool waitImpl(long milliseconds);
    
        std::atomic<bool>       _state; // 状态信号量
        bool                    _autoreset; // 是否自动重置
        mutable std::mutex      _mutex;
        std::condition_variable _cond;
    

    wait相关函数

    void Event::wait()
    {
        try
        {
            std::unique_lock<std::mutex> lock(_mutex);
            while (!_state)
                _cond.wait(lock, [this]() { return this->_state.load(); });
            if (_autoreset) _state = false;
        }
        catch (std::system_error &e)
        {
            throw SystemException(e.what());
        }
    }
    
    bool Event::waitImpl(long milliseconds)
    {
        try
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = _cond.wait_for(lock, std::chrono::milliseconds(milliseconds), [this]() { return this->_state.load(); });
            if (ret && _autoreset) _state = false;
            return ret;
        }
        catch (std::system_error &e)
        {
            throw SystemException(e.what());
        }
    }
    
    inline void Event::wait(long milliseconds)
    {
        if (!waitImpl(milliseconds)) throw TimeoutException();
    }
    
    inline bool Event::tryWait(long milliseconds)
    {
        return waitImpl(milliseconds);
    }
    

    从源码可以看到,如果state为false,则通过conditional_variable等待信号。
    如果设置了autoreset,则state=true后会立刻被重置回false。
    这里有一点不明白,为什么atomic类型的还要加锁??

    set相关函数

    void Event::set()
    {
        try
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _state = true;
            if (_autoreset) _cond.notify_one();
            else            _cond.notify_all();
        }
        catch (std::system_error &e)
        {
            throw SystemException(e.what());
        }
    }
    
    
    void Event::reset()
    {
        try
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _state = false;
        }
        catch (std::system_error &e)
        {
            throw SystemException(e.what());
        }
    }
    

    Event使用一个简单的示例

    void notify1(Event& event) {
        event.wait();
        cout<<"You released notify1"<<endl;
    }
    
    void notify2(Event& event) {
        event.wait();
        cout<<"You released notify2"<<endl;
    }
    
    
    int main(int argc, char **argv) {
        Event event;
        cout << "[" << time_str() << "]begin to wait" << endl;
        thread thread1(notify1, ref(event));
        thread thread2(notify2, ref(event));
        this_thread::sleep_for(chrono::milliseconds(200));
        cout << "[" << time_str() << "]send singal" << endl;
        event.set();
    
        thread1.join();
        thread2.join();
    
        return 0;
    }
    

    执行结果为


    异常执行结果.PNG

    为何不是两个都接收到信号呢? 因为Event初始化的时候,默认autoreset是true。也就是说一个信号收到后会立刻将state重置。

    所以要稍微修改一下:

    int main(int argc, char **argv) {
        Event event(false); // <-----------------------false!
        cout << "[" << time_str() << "]begin to wait" << endl;
        thread thread1(notify1, ref(event));
        thread thread2(notify2, ref(event));
        this_thread::sleep_for(chrono::milliseconds(200));
        cout << "[" << time_str() << "]send singal" << endl;
        event.set();
    
        thread1.join();
        thread2.join();
    
        return 0;
    }
    

    运行结果


    正常.PNG

    相关文章

      网友评论

          本文标题:【Poco笔记】Event——mutex和conditional

          本文链接:https://www.haomeiwen.com/subject/qiyjzftx.html