Blocking queue is multi-threaded thread-safe queues, often used in multithreaded scenarios, c ++ standard library which did not provide a blocking queue, boost has provided, you can use the next generation environment
blocking queue achieve
The main design ideas:
- Used
std::vector
to implement a circular queue, using the two start and end pointers identifying the beginning and ending positions, Push when inserted at the end, pop start directly when the pointer moves back to - Use
std::condition_variable
synchronized, push the time required to meet_not_full
the conditions, push send complete_not_empty
notification, pop when the need to meet_not_empty
the conditions, pop finished sending_not_full
notification
template <typename T>
class BlockingQueue {
std::mutex _mutex;
std::condition_variable _not_full;
std::condition_variable _not_empty;
int _start;
int _end;
int _capacity;
std::vector<T> _vt;
public:
BlockingQueue(const BlockingQueue<T>& other) = delete;
BlockingQueue<T>& operator=(const BlockingQueue<T>& other) = delete;
BlockingQueue(int capacity) : _capacity(capacity), _vt(capacity + 1), _start(0), _end(0) {}
bool isempty() {
return _end == _start;
}
bool isfull() {
return (_start + _capacity - _end) % (_capacity + 1) == 0;
}
void push(const T& e) {
std::unique_lock<std::mutex> lock(_mutex);
while (isfull()) {
_not_full.wait(lock);
}
_vt[_end++] = e;
_end %= (_capacity + 1);
_not_empty.notify_one();
}
T pop() {
std::unique_lock<std::mutex> lock(_mutex);
while (isempty()) {
_not_empty.wait(lock);
}
auto res = _vt[_start++];
_start %= (_capacity + 1);
_not_full.notify_one();
return res;
}
};
Consumers creator
Continue to queue thread creator face insert a random number taken from the queue consumer thread inside
void producer(BlockingQueue<int>& q, int i) {
while (true) {
std::random_device rd;
auto p = rd() % 10;
q.push(p);
std::cout << "produce " << i << " [" << p << "]" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1500 + rd() % 5000));
}
}
void consumer(BlockingQueue<int>& q, int i) {
while (true) {
std::random_device rd;
auto p = q.pop();
std::cout << "consume " << i << " [" << p << "]" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1500 + rd() % 5000));
}
}
void producerConsumer() {
BlockingQueue<int> q(4);
std::vector<std::thread> ps(10);
std::vector<std::thread> cs(20);
for (int i = 0; i < ps.size(); i++) {
ps[i] = std::thread(producer, std::ref(q), i);
}
for (int i = 0; i < cs.size(); i++) {
cs[i] = std::thread(consumer, std::ref(q), i);
}
for (int i = 0; i < ps.size(); i++) {
ps[i].join();
}
for (int i = 0; i < ps.size(); i++) {
cs[i].join();
}
}
link
- Complete code: https://github.com/hpifu/md-tech/blob/master/hatlonely/code/blocking-queue/blocking-queue.cpp
Please indicate the source
article link: https://tech.hatlonely.com/article/60