/*
 * BlockingQueue.hpp
 *
 *  Created on: May 17, 2018
 *      Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert, Rafael Vinci, Dr. Franca Rupprecht
 */

#ifndef SRC_UTILITIES_BLOCKINGQUEUE_HPP_
#define SRC_UTILITIES_BLOCKINGQUEUE_HPP_

#include <mutex>
#include <condition_variable>
#include <boost/heap/priority_queue.hpp>

#include "IBlockingQueue.h"

using namespace boost;

namespace flippR_driver
{
namespace utility
{

template<typename T>
class BlockingQueue : public IBlockingQueue<T>
{
private:
  std::mutex d_mutex;
  std::condition_variable d_condition;
  heap::priority_queue<T, heap::stable<true>> p_queue;

public:
  void push(T const &value)
  {
    {
      std::unique_lock<std::mutex> lock(this->d_mutex);
      p_queue.push(value);
    }
    this->d_condition.notify_one();
  }

  T pop()
  {
    std::unique_lock<std::mutex> lock(this->d_mutex);
    this->d_condition.wait(lock, [=]
      { return !this->p_queue.empty(); });
    T rc = *this->p_queue.begin();
    this->p_queue.pop();
    return rc;
  }
};
}
}



#endif