1. 程式人生 > 實用技巧 >muduo原始碼解析17-(bounded)blockingqueue類

muduo原始碼解析17-(bounded)blockingqueue類

blockingqueue和boundedblockingqueue

作用:

無邊界blockingqueue:

實現了一個有鎖的dequeue雙端佇列
保證put,take,size操作都具有原子性
內部使用互斥鎖mutexlock,再使用一個條件變數用於判斷佇列是否為空

有邊界boundedblockingqueue:

實現了一個有邊界的雙端佇列,實現執行緒安全,對常用的操作加鎖,實現原子性
內部使用boost::circular_buffer來儲存資料

兩個類都比較簡單

blockingqueue:

/*
實現了一個有鎖的dequeue雙端佇列
保證put,take,size操作都具有原子性
內部使用互斥鎖mutexlock,再使用一個條件變數用於判斷佇列是否為空
*/ #ifndef BLOCKINGQUEUE_H #define BLOCKINGQUEUE_H #include"base/condition.h" #include"base/mutex.h" #include<deque> #include<assert.h> namespace mymuduo { template <typename T> class blockingqueue:noncopyable { public: blockingqueue():m_mutex(),m_notEmpty(m_mutex),m_queue() { }
//隊尾新增元素 void put(const T& x) { mutexlockguard mlg(m_mutex); m_queue.push_back(x); m_notEmpty.notify(); } void put(T&& x) { mutexlockguard mlg(m_mutex); //std::move把左值轉化成右值引用 m_queue.push_back(std::move(x)); m_notEmpty.notify(); }
//隊頭取出元素 T take() { mutexlockguard mlg(m_mutex); while(m_queue.empty()) m_notEmpty.wait(); assert(!m_queue.empty()); T val=std::move(m_queue.front()); m_queue.pop_front(); return val; } size_t size() const { mutexlockguard mlg(m_mutex); return m_queue.size(); } private: //mutable修飾的成員變數可以在常成員函式中修改 mutable mutexlock m_mutex; condition m_notEmpty; std::deque<T> m_queue; }; } #endif // BLOCKINGQUEUE_H

boundedblockingqueue:

/*
實現了一個有邊界的佇列,實現執行緒安全,對常用的操作加鎖,實現原子性
內部使用boost::circular_buffer來儲存資料
*/

#ifndef BOUNDEDBLOCKINGQUEUE_H
#define BOUNDEDBLOCKINGQUEUE_H

#include"base/condition.h"
#include"base/mutex.h"

#include<boost/circular_buffer.hpp>
#include<assert.h>


namespace mymuduo {

template <typename T>
class boundedblockingqueue:noncopyable
{
public:
    explicit boundedblockingqueue(int maxSize)
        :m_mutex(),m_notEmpty(m_mutex),m_notFull(m_mutex),m_queue(maxSize)
    {

    }
    //新增元素
    void put(const T& x)
    {
        mutexlockguard mlg(m_mutex);
        while(m_queue.full())
            m_notFull.wait();
        assert(!m_queue.full());
        m_queue.push_back(x);
        m_notEmpty.notify();
    }

    void put(const T&& x)
    {
        mutexlockguard mlg(m_mutex);
        while(m_queue.full())
            m_notFull.wait();
        assert(!m_queue.full());
        m_queue.push_back(std::move(x));
        m_notEmpty.notify();
    }
    //取出元素
    T take()
    {
        mutexlockguard mlg(m_mutex);
        while(m_queue.empty())
            m_notEmpty.wait();

        assert(!m_queue.empty());
        T val=std::move(m_queue.front());
        m_queue.pop_front();
        m_notFull.notify();
        return val;
    }
    //返回佇列各種狀態...
    bool empty() const
    {
        mutexlockguard mlg(m_mutex);
        return m_queue.empty();
    }

    bool full() const
    {
        mutexlockguard mlg(m_mutex);
        return m_queue.full();
    }

    size_t size() const
    {
        mutexlockguard mlg(m_mutex);
        return m_queue.size();
    }

    size_t capacity() const
    {
        mutexlockguard mlg(m_mutex);
        return m_queue.capacity();
    }

private:
    mutable mutexlock m_mutex;
    condition m_notEmpty;
    condition m_notFull;
    boost::circular_buffer<T> m_queue;

};


}//namespace mymuduo




#endif // BOUNDEDBLOCKINGQUEUE_H

兩個類都比較簡單,在常用的操作上加鎖實現執行緒安全,這裡不再測試了。