spdlog-mpmc_bounded_q.h 无锁队列源码分析

spdlog–mpmc_bounded_q.h 无锁队列分析

spdlog中调用了mpmc_bounded_q.h无锁队列实现异步写日志。

构造函数

构造函数传入buffer最大值,并初始化了buffer数组buffer_以及buffer_mask_

  • buffer_size必须是2的幂次方。
  • 设置每个buffer[i]的值为其序号。
  • 设置入队、出队位置为0。
    mpmc_bounded_queue(size_t buffer_size)
        :max_size_(buffer_size),
         buffer_(new cell_t [buffer_size]),
         buffer_mask_(buffer_size - 1)
    {
        //queue size must be power of two
        if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
            throw spdlog_ex("async logger queue size must be power of two");

        for (size_t i = 0; i != buffer_size; i += 1)
            buffer_[i].sequence_.store(i, std::memory_order_relaxed);
        enqueue_pos_.store(0, std::memory_order_relaxed);
        dequeue_pos_.store(0, std::memory_order_relaxed);
    }

入队函数 bool enqueue(T&& data)

  1. 获取插入的位置pos = enqueue_pos_
  2. 获取pos处的buffer_, 即cell_
  3. 判断pos是否等于cell_->sequence_
  4. 若相等,尝试占领pos这个位置(enqueue_pos_.compare_exchange_weak),让enqueue_pos_加一,跳出循环
  5. cell_->sequence_ < pos, 队列中保存的数据已达到max_size_,不入队
  6. cell_->sequence_ > pos,说明cell_处已经被写入数据,更新pos,重新进入第2步

疑问

cell->sequence_.store(pos + 1, std::memory_order_release);,这里困扰我一阵,为什么要将cell的sequence设为pos+1?

个人见解

我觉得主要作用是标记pos处已经放置数据了。若其他线程获得相同的pos,当其再比较pos和sequence时将不会再相等,就不会再次在相同的pos处写入数据。另外,此处的pos+1和出队时的判断intptr_t dif = (intptr_t)seq - (intptr_t)(pos + 1);相对应。

    bool enqueue(T&& data) // 传入待插入数据的右值引用
    {
        cell_t* cell;
        size_t pos = enqueue_pos_.load(std::memory_order_relaxed); // 获取插入的位置
        for (;;)  //一直循环,直到enqueue_pos_.compare_exchange_weak返回true
        {
            cell = &buffer_[pos & buffer_mask_];  // 取出一个buffer_
            size_t seq = cell->sequence_.load(std::memory_order_acquire); // 取出buffer_自己的序号
            intptr_t dif = (intptr_t)seq - (intptr_t)pos;
            if (dif == 0
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值