C++11實現生產者消費者模式

併發編程中,數據產生和數據處理在不同的線程,這些線程傳遞數據常用的就是生產者消費者模式

以下是模仿Java的BlockingQueue實現的生產者消費者模式:

#pragma once
#include <queue>
#include <mutex>
#include <condition_variable>


enum PopResult{ POP_OK, POP_STOP, POP_UNEXPECTED };

template<class T>
class BlockingQueue : public std::queue<T>
{
public:
    std::mutex m_lock;
    std::condition_variable m_cond;
    bool m_stopFlag = false;


    virtual ~BlockingQueue() = default;

    void push(const T& value)
    {
        std::lock_guard<decltype(m_lock)> lock(m_lock);
        queue::push(value);
        m_cond.notify_one();
    }

    void push(T&& value)
    {
        std::lock_guard<decltype(m_lock)> lock(m_lock);
        queue::push(std::move(value));
        m_cond.notify_one();
    }

    PopResult pop(T& out)
    {
        std::unique_lock<decltype(m_lock)> lock(m_lock);
        if (m_stopFlag) // 停止
            return POP_STOP;
        if (empty())
            m_cond.wait(lock);
        if (m_stopFlag) // 停止
            return POP_STOP;
        if (empty()) // 意外喚醒?
            return POP_UNEXPECTED;

        out = std::move(front());
        queue::pop();
        return POP_OK;
    }

    void Stop()
    {
        std::lock_guard<decltype(m_lock)> lock(m_lock);
        m_stopFlag = true;
        m_cond.notify_all();
    }
};

使用方法:

#include <iostream>
#include <thread>


BlockingQueue<int> g_queue;


// 生產者線程
void Produce()
{
    for (int i = 0; i < 10; ++i)
        g_queue.push(i);
}

// 消費者線程
void Consume()
{
    int data;
    while (true)
    {
        // 取數據
        PopResult res = g_queue.pop(data);
        if (res == POP_STOP) // 線程應該停止
            break;
        if (res == POP_UNEXPECTED) // 意外喚醒
            continue;

        // 處理數據
        std::cout << data << std::endl;
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    // 啓動生產者線程和消費者線程(也可以啓動多個線程)
    std::thread produceThread(Produce);
    std::thread consumerThread(Consume);

    // 等待數據處理完
    Sleep(1000);

    produceThread.join();
    // 停止線程
    g_queue.Stop();
    consumerThread.join();

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章