2016-10-15 4 views
0

1つのプロバイダと複数のコンシューマに対して、サイズが制限されたブロックキューを実装しようとしています。消費者が1秒間眠っているときはうまく働いていますが、睡眠がないときはハングアップします。 私は何が間違っていますか?ここC++ stdキューを使用したブロックキュー

は私のコードです:ここでは

#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; 
    } 
+4

単一のミューテックスが十分でなければなりません。あなたはwronトラックにいます。 –

+0

また、キューに新しい要素を追加した後、 'notEmpty()'はtrueになることが保証されています。したがって 'if(notEmpty())'は時間の無駄です。要素をポップした後の 'if(!Full())'のことです。さらに、コンストラクタ本体の 'queue ()'はまったく役に立たず、全く何も実行しません。 –

+0

1つのミューテックスを使用すると、キューがいっぱいになってキューが空のときにライターがロックされます。それは動作しません。 キューがいっぱいのときは書き込みブロッキングが必要で、キューが空のときは読み取りブロッキングが必要です。 – nubee

答えて

0

は、複数のプロバイダと複数のコンシューマと限られたキューサイズとキューを阻止するための私の固定コードです:

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; 
}; 
関連する問題