I learned about atomic variables, and know the operation of atomic variables.
Next, I want to use atomic variables to implement a bounded lock-free queue. I plan to use two variables to represent the head and tail of the queue.
template <typename T>
class BoundedQueue {
public:
void enqueue(const T& t);
private:
T* data_;
std::atomic<uint64_t> head_;
std::atomic<uint64_t> tail_;
};
template <typename T>
void BoundedQueue::enqueue(const T& t) {
auto h_t = head_.load();
while(!head_.compare_exchange_weak(h_t, h_t+1)) {
;
}
data_[h_t] = t;
}
- Although enqueue can increase atomically. But
I can’t know if the queue is full, otherwise I need to implement the following logic
if (head_.load() > tail_.load() + capacity) {
// the queue is full
}
I know that the above process is not atomic, but how do I get the length of the current queue?
- I see the following comparison in
folly'sfolly\ProducerConsumerQueue.h
bool isEmpty() const {
return readIndex_.load(std::memory_order_acquire) ==
writeIndex_.load(std::memory_order_acquire);
}
Can someone explain the reason in detail?
additional
I understand the implementation in folly, because it restricts SPSC, so the producer thread only needs to know the value of head_, and it knows the value of tail by itself, so it can be guaranteed to be atomic, but once it leaves SPSC, it doesn’t hold.
* ProducerConsumerQueue is a one producer and one consumer queue
* without locks.