cpp无锁环队(RingBuffer)

cpp无锁环队(RingBuffer)简单实现

设计简介

  1. 单例模式,节约内存,方便操作。
  2. 出队和入队采用无锁实现。
  3. 队列判空方式:read_index == write_index 。
  4. 队列判满方式:(write_index + 1) % size == read_index 。
#include <atomic>
#include <cstddef>
#include <cstdio>
#include <mutex>
#include <thread>
#include <chrono>

constexpr int kTestTimes = 15;

template <typename T>
class RingBuffer {
 public:
  static RingBuffer &Instance() {
    static RingBuffer instance;
    return instance;
  }

  void Init(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;
  }

  bool Enqueue(const T &data) {

    if (!inited_) {
      return false;
    }
    // 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);
      return true;
    }
    return false;
  };

  bool Dequeue(T &data) {
    if (!inited_) {
      return false;
    }
    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);
      return true;
    }
    return false;
  }

  ~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_;
  }

  static const int kDefaultSize = 5;

  std::atomic<size_t> read_index_;
  std::atomic<size_t> write_index_;
  size_t size_;
  T *buffer_;
  bool inited_;
  std::mutex mtx_;

  
};

void WriterThread() {
    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));
    }
}

// 测试读线程函数
void ReaderThread() {
    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));
    }
}

int main() {
    RingBuffer<int>::Instance().Init();
    RingBuffer<int>::Instance().Init(10);
    std::thread writer(WriterThread);
    std::thread reader(ReaderThread);

    writer.join();
    reader.join();

    return 0;
}

测试结果

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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值