Synchronized Queue Wrapper C++11 I am trying to write a SynchronizedQueue wrapper class to provide a simple synchronized interface to underlying standard std::queue.
Could you have a review and let me know if any pitfalls and improvements you see ?
Too many mutexes/locks ? I wanted to to use condition variables to wait rather than mutexes for push &amp; pop notifications.
Any insights is highly appreciated as I have rarely written multi-threaded programs.   

#pragma once

#include &lt;mutex&gt;
#include &lt;condition_variable&gt;
#include &lt;queue&gt;
#include &lt;cstdint&gt;

template&lt;typename T&gt;
class SynchronizedQueue
{
public:
  SynchronizedQueue(size_t maxItems)
    : synchronizedQueue_()
    , queueMutex_()
    , pushMutex_()
    , popMutex_()
    , pushCV_()
    , popCV_()
    , MAX_ITEMS(maxItems)
  {
  }

  void push(const T&amp; item)
  {
    std::unique_lock&lt;std::mutex&gt; scopedLock(pushMutex_);
    while (isFull())
    {
      std::unique_lock&lt;std::mutex&gt; pushLock(queueMutex_);
      popCV_.wait(pushLock);
    }

    {
      std::unique_lock&lt;std::mutex&gt; scopedLock(queueMutex_);
      synchronizedQueue_.push(item);
      pushCV_.notify_one();
    }
  }

  T pop()
  {
    std::unique_lock&lt;std::mutex&gt; scopedLock(popMutex_);
    while (isEmpty())
    {
      std::unique_lock&lt;std::mutex&gt; scopedLock(queueMutex_);
      pushCV_.wait(scopedLock);
    }

    T t;
    {
      std::unique_lock&lt;std::mutex&gt; scopedLock(queueMutex_);
      t = synchronizedQueue_.front();
      synchronizedQueue_.pop();
      popCV_.notify_one();
    }

    return t;
  }


private:
  bool isEmpty()
  {
    std::unique_lock&lt;std::mutex&gt; scopedLock(queueMutex_);
    return synchronizedQueue_.empty();
  }

  bool isFull()
  {
    std::unique_lock&lt;std::mutex&gt; scopedLock(queueMutex_);
    return synchronizedQueue_.size() == MAX_ITEMS;
  }

  std::queue&lt;T&gt; synchronizedQueue_;
  std::mutex queueMutex_, pushMutex_, popMutex_;
  std::condition_variable pushCV_, popCV_;
  size_t MAX_ITEMS;
};
Synchronization

pushMutex_ and popMutex_ aren't needed. Even worse, they prevent other threads from waiting on a condition variable! Just lock queueMutex_ instead (that also prevents having to re-lock queueMutex_).

Assume that the queue is full, and thread 1 and 2 both want to push an item into the queue. Thread 1 was faster and got the lock on pushMutex_, so it proceeds to wait on pushCV_. Thread 2 in the meanwhile spins trying to lock pushMutex_ - which is still held by thread 1!


Avoid using std::condition_variable::notifiy_one() while still holding the corresponding lock! The notified thread will wake up, and the first action it has to do is reacquiring the lock that is still hold by the caller of notify_one(), so it will instantly block again (this time on acquiring the lock though, not wait()).


Implementation

The outer scopedLock in push() and pop() get shadowed by the inner scopedLock. This can lead to extra confusion in an already complex code!

Since MAX_SIZE isn't supposed to change once the object is initialized, consider marking it as const. (It can still be set with the initialization list of the constructor, but not changed afterwards.)


Further considerations

Maybe add fast returning bool try_push(const T&amp;) and bool try_pop(T&amp;) member functions, so users of the queue don't have to wait if they don't need to?