简体   繁体   中英

blocking queue using c++ std queue

I'm trying to implement a blocking queue with limited size, for one provider and multiple consumers. it is working well when the consumer is sleep()ing for 1 second, but hangs when there is no sleep. what am I doing wrong?

here is my code:

    #include <iostream>
    #include <stdlib.h>
    #include <unistd.h>
    #include <thread>
    #include <queue>
    #include <mutex>
    #include <condition_variable>

    using namespace std;
    template <class T> class BlockingQueue: public queue<T> {
        public:
            BlockingQueue() {
                queue<T>();
            }

            BlockingQueue(int size) {
                maxSize = size;
                queue<T>();
            }

            void push(T item) {
                unique_lock<std::mutex> wlck(writerMutex);
                while(Full())
                    isFull.wait(wlck);
                queue<T>::push(item);
                if(notEmpty()) 
                    isEmpty.notify_one();
            }

            bool notEmpty() {
                return !queue<T>::empty();
            }

            bool Full(){
                return queue<T>::size() >= maxSize;
            }

        T pop() {
            unique_lock<std::mutex> lck(readerMutex);

            popMutex.lock();    
            while(queue<T>::empty()) {
                isEmpty.wait(lck);
            }
            T value = queue<T>::front();
            queue<T>::pop();
            if(!Full())
                isFull.notify_all();
            popMutex.unlock();
            return value;
        }

        private:
            int maxSize;
            std::mutex readerMutex;
            std::mutex popMutex;
            std::mutex writerMutex;
            condition_variable isFull;
            condition_variable isEmpty;
    };
    void runProvider(BlockingQueue<int>* Q) {
        int number=0;
        while(1) {
            Q->push(number);
            cout<<"provide "<<number<<endl;
            number++;
        }
    }

    void runConsumer(int n,BlockingQueue<int>* Q) {
        int number;
        while(1) {
            number = Q->pop();
            cout<<"consume#"<<n<<": "<<number<<endl;
        }
    }

    int main(int argc, char** argv) {
        BlockingQueue<int> *Queue = new BlockingQueue<int>(10);
        cout<<"starting provider"<<endl;
        std:thread provider(runProvider, Queue);
        sleep(1);

        cout<<"starting consumer"<<endl;
        std::thread consumer1(runConsumer, 1,Queue);
        std::thread consumer2(runConsumer, 2,Queue);

        provider.join();
        delete(Queue);
        return 0;
    }

Here is my fixed code for blocking queue with multiple providers and multiple consumers and limited queue size:

template <class T> class BlockingQueue: public queue<T> {
    public:
        BlockingQueue(int size) {
            maxSize = size;
        }

        void push(T item) {
            unique_lock<std::mutex> wlck(writerMutex);
            while(Full())
                isFull.wait(wlck);
            queue<T>::push(item);
            isEmpty.notify_all();
        }

        bool notEmpty() {
            return !queue<T>::empty();
        }

        bool Full(){
            return queue<T>::size() >= maxSize;
        }

    T pop() {
        unique_lock<std::mutex> lck(readerMutex);
        while(queue<T>::empty()) {
            isEmpty.wait(lck);
        }
        T value = queue<T>::front();
        queue<T>::pop();
        if(!Full())
            isFull.notify_all();
        return value;
    }

    private:
        int maxSize;
        std::mutex readerMutex;
        std::mutex writerMutex;
        condition_variable isFull;
        condition_variable isEmpty;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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