Zeromq yqueue 实现

首次听到"无锁队列"时,总会有这样的印象:多线程读写且不需要同步的强大的数据结构。当然,这是不可能的。

所谓的无锁队列,非但不是无锁的,往往还有很多条件限制。

zeromq源码yqueue.hpp注释,已经说明了一切。

    //  yqueue is an efficient queue implementation. The main goal is
    //  to minimise number of allocations/deallocations needed. Thus yqueue
    //  allocates/deallocates elements in batches of N.
    //
    //  yqueue allows one thread to use push/back function and another one
    //  to use pop/front functions. However, user must ensure that there's no
    //  pop on the empty queue and that both threads don't access the same
    //  element in unsynchronised manner.

yqueue的使用是先back/front进行写读操作,再通过push/pop更新数据结构。一开始看到注释里push/back、pop/front还挣扎了一段时间,以为是先push/pop再back/front进行操作的。

见zeromq中yqueue的使用,ypipe.hpp:

        inline void write (const T &value_, bool incomplete_)
        {
            //  Place the value to the queue, add new terminator element.
            queue.back () = value_;
            queue.push ();


            //  Move the "flush up to here" poiter.
            if (!incomplete_)
                f = &queue.back ();
        }
front/pop的使用顺序同样可以在zeromq的源码找到。

为什么一个线程读,另一个线程写不需要进行同步呢?其实不需要同步这种说法是错误的,实际上也是做了同步的。

back和front方法通过back_pos 和begin_pos来定位元素,当然不需要同步,但pop和push方法访问了同一变量spare_chunk,是需要同步的。

spare_chunk中的xchg和CAS即是同步。

#elif defined ZMQ_ATOMIC_PTR_X86
            T *old;
            __asm__ volatile (
                "lock; cmpxchg %2, %3"
                : "=a" (old), "=m" (ptr)
                : "r" (val_), "m" (ptr), "0" (cmp_)
                : "cc");
            return old;
其实在单核环境下,CAS也不需要lock     只有在SMP环境下,才需要。

stackoverflow

DPDK中ring buff也是类似实现。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值