As part of my own C++11 learning exercise I have implemented this Blocking Queue using the new C++11 thread API. One of the aspects I would like to improve is efficiency i.e. in the take
member function while returning the Job
template type to be returned by reference instead of by value.
/*
* blockingqueue.h
*
* Created on: May 20, 2016
* Author: bravegag
*/
#ifndef BLOCKINGQUEUE_H_
#define BLOCKINGQUEUE_H_
#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>
#include <cassert>
using namespace std;
template<class Job>
class blocking_queue {
private:
queue<Job> queue_;
mutex mutex_;
condition_variable not_empty_cond_;
condition_variable not_full_cond_;
int capacity_ = 0;
public:
blocking_queue(int capacity) : capacity_(capacity) {
// empty
}
void put(const Job& job) {
unique_lock<mutex> lock(mutex_);
while (queue_.size() >= capacity_) {
cout << "queue full, waiting for jobs to be taken" << endl;
not_full_cond_.wait(lock, [&]() { return (queue_.size() < capacity_); } );
}
queue_.push(job);
not_empty_cond_.notify_one();
assert(!queue_.empty());
}
Job take() {
unique_lock<mutex> lock(mutex_);
while (queue_.empty()) {
cout << "queue empty, waiting for jobs to be put" << endl;
not_empty_cond_.wait(lock, [&]() { return !queue_.empty(); });
}
Job job = queue_.front();
queue_.pop();
not_full_cond_.notify_one();
assert(queue_.size() < capacity_);
return job;
}
int size() const {
return queue_.size();
}
virtual ~blocking_queue() {
// empty
}
};
#endif /* BLOCKINGQUEUE_H_ */