#include<atomic>#include<cstddef>#include<cstdio>#include<mutex>#include<thread>#include<chrono>constexprint kTestTimes =15;template<typenameT>classRingBuffer{public:static RingBuffer &Instance(){static RingBuffer instance;return instance;}voidInit(size_t size = kDefaultSize){
std::lock_guard<std::mutex>lock(mtx_);if(inited_){printf("Already initialized, duplicate initialization is not allowed\n");return;}try{
buffer_ =new T[size];}catch(const std::bad_alloc &e){printf("Failed to allocate memory for the buffer: %s\n", e.what());return;}
size_ = size;
read_index_.store(0, std::memory_order_relaxed);
write_index_.store(0, std::memory_order_relaxed);
inited_ =true;printf("Init RingBuffer done, size is: %d\n",(int)size_);return;}boolEnqueue(const T &data){if(!inited_){returnfalse;}// check if queue is full
size_t current_write = write_index_.load(std::memory_order_relaxed);
size_t next_write =IncrementIndex(current_write);if(next_write != read_index_.load(std::memory_order_acquire)){
buffer_[current_write]= data;
write_index_.store(next_write, std::memory_order_release);returntrue;}returnfalse;};boolDequeue(T &data){if(!inited_){returnfalse;}
size_t current_read = read_index_.load(std::memory_order_relaxed);if(current_read != write_index_.load(std::memory_order_acquire)){
data = buffer_[current_read];
read_index_.store(IncrementIndex(current_read),
std::memory_order_release);returntrue;}returnfalse;}~RingBuffer(){if(inited_){delete[] buffer_;
inited_ =false;}}private:RingBuffer()=default;RingBuffer(const RingBuffer &)=delete;
RingBuffer &operator=(const RingBuffer &)=delete;RingBuffer(const RingBuffer &&)=delete;
size_t IncrementIndex(const size_t index)const{return(index +1)% size_;}staticconstint kDefaultSize =5;
std::atomic<size_t> read_index_;
std::atomic<size_t> write_index_;
size_t size_;
T *buffer_;bool inited_;
std::mutex mtx_;};voidWriterThread(){auto&buffer =RingBuffer<int>::Instance();for(int i =1; i <= kTestTimes;++i){bool success = buffer.Enqueue(i);if(success){printf("Writer: Enqueued: %d\n", i);}else{printf("Writer: Buffer is full. Unable to enqueue %d\n", i);}
std::this_thread::sleep_for(std::chrono::milliseconds(200));}}// 测试读线程函数voidReaderThread(){
RingBuffer<int>& buffer =RingBuffer<int>::Instance();for(int i =1; i <= kTestTimes;++i){int value;bool success = buffer.Dequeue(value);if(success){printf("Reader: Dequeued: %d\n", value);}else{printf("Reader: Buffer is empty. Unable to dequeue.\n");}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));}}intmain(){RingBuffer<int>::Instance().Init();RingBuffer<int>::Instance().Init(10);
std::thread writer(WriterThread);
std::thread reader(ReaderThread);
writer.join();
reader.join();return0;}
测试结果
Init RingBuffer done, size is: 5
Already initialized, duplicate initialization is not allowed
Writer: Enqueued: 1
Reader: Dequeued: 1
Writer: Enqueued: 2
Writer: Enqueued: 3
Writer: Enqueued: 4
Writer: Enqueued: 5
Reader: Dequeued: 2
Writer: Enqueued: 6
Writer: Buffer is full. Unable to enqueue 7
Writer: Buffer is full. Unable to enqueue 8
Writer: Buffer is full. Unable to enqueue 9
Writer: Buffer is full. Unable to enqueue 10
Reader: Dequeued: 3
Writer: Enqueued: 11
Writer: Buffer is full. Unable to enqueue 12
Writer: Buffer is full. Unable to enqueue 13
Writer: Buffer is full. Unable to enqueue 14
Writer: Buffer is full. Unable to enqueue 15
Reader: Dequeued: 4
Reader: Dequeued: 5
Reader: Dequeued: 6
Reader: Dequeued: 11
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.
Reader: Buffer is empty. Unable to dequeue.