#ifndef SAFE_QUEUE
#define SAFE_QUEUE

#include <condition_variable>
#include <mutex>
#include <queue>

namespace WHISPER {

  // A threadsafe-queue.
  template <class T>
  class threadSafeQueue
  {
  public:
      threadSafeQueue() : q(), m(), c() {}

      ~threadSafeQueue() {}

      // Add an element to the queue.
      void addElement(T t)
      {
          std::lock_guard<std::mutex> lock(m);
          q.push(t);
          c.notify_one();
      }

      // Get the front element.
      // If the queue is empty, wait till a element is avaiable.
      T get(void)
      {
          std::unique_lock<std::mutex> lock(m);
          while (q.empty())
          {
              // release lock as long as the wait and reaquire it afterwards.
              c.wait(lock);
          }
          T val = q.front();
          q.pop();
          return val;
      }
      unsigned int size()
      {
        std::unique_lock<std::mutex> lock(m);
        return q.size();
      }

  private:
      std::queue<T> q;
      mutable std::mutex m;
      std::condition_variable c;
  };
}
#endif