无锁的环形队列

#ifndef _RingQueue_H_
#define _RingQueue_H_
#include <memory.h>
template<class T, unsigned int MAX_LEN = 1024>
class RingQueue
{
public:

    //-----------------------------------------------------
    // 构造
    //-----------------------------------------------------
    RingQueue()
    {
        m_nHead = 0;
        m_nTail = 0;
    }

    //-----------------------------------------------------
    // 析构
    //-----------------------------------------------------
    ~RingQueue()
    {

    }

    //-----------------------------------------------------
    // 重置,清空队列
    //-----------------------------------------------------
    void    Reset()
    {
        m_nHead = 0;
        m_nTail = 0;
    }

    //-----------------------------------------------------
    // 取得最多读取个数
    //-----------------------------------------------------
    unsigned int        GetMaxReadSize()
    {
        int size = (m_nTail - m_nHead + MAX_LEN) % MAX_LEN;
        return size;
    }

    //-----------------------------------------------------
    // 取得最多写入个数
    //-----------------------------------------------------
    unsigned int        GetMaxWriteSize()
    {
        int size = (m_nHead - m_nTail + MAX_LEN - 1) % MAX_LEN;
        return size;
    }

    //-----------------------------------------------------
    // 添加数据
    //-----------------------------------------------------
    bool    PushData(const T* pData, unsigned int nLength = 1)
    {
        if (pData == nullptr || nLength > GetMaxWriteSize())
        {
            return false;
        }

        if (m_nTail + nLength <= MAX_LEN)
        {
            memcpy(m_Buffer + m_nTail, pData, nLength * sizeof(T));
            m_nTail = (m_nTail + nLength) % MAX_LEN;
        }
        else
        {
            unsigned int size1 = MAX_LEN - m_nTail;
            unsigned int size2 = nLength - size1;

            memcpy(m_Buffer + m_nTail, pData, size1 * sizeof(T));
            memcpy(m_Buffer, pData+size1, size2 * sizeof(T));

            m_nTail = size2;
        }

        return true;
    }

    //-----------------------------------------------------
    // 取出并删除数据
    //-----------------------------------------------------
    bool    PopData(T* pData, unsigned int nLength = 1)
    {
        if (pData == nullptr || nLength > GetMaxReadSize() || nLength <= 0)
        {
            return false;
        }

        if (m_nHead + nLength <= MAX_LEN)
        {
            memcpy(pData, m_Buffer + m_nHead, nLength * sizeof(T));
            m_nHead    = (m_nHead + nLength) % MAX_LEN;
        }
        else
        {
            unsigned int size1 = MAX_LEN - m_nHead;
            unsigned int size2 = nLength - size1;

            memcpy(pData, m_Buffer + m_nHead, size1 * sizeof(T));
            memcpy(pData + size1, m_Buffer, size2 * sizeof(T));

            m_nHead = size2;
        }

        return true;
    }

    //-----------------------------------------------------
    // 查看数据 不删除
    //-----------------------------------------------------
    bool    PeekData(T* pData, unsigned int nLen)
    {
        if (nLen > GetMaxReadSize() || nLen <= 0)
        {
            return false;
        }

        if (m_nHead + nLen <= MAX_LEN)
        {
            memcpy(pData, m_Buffer + m_nHead, nLen * sizeof(T));
        }
        else
        {
            unsigned int size1 = MAX_LEN - m_nHead;
            unsigned int size2 = nLen - size1;

            memcpy(pData, m_Buffer + m_nHead, size1 * sizeof(T));
            memcpy(pData + size1, m_Buffer, size2 * sizeof(T));
        }

        return true;
    }

    //-----------------------------------------------------
    // 删除数据
    //-----------------------------------------------------
    bool    DeleteData(unsigned int nLen)
    {
        if (nLen > GetMaxReadSize() || nLen <= 0)
        {
            return false;
        }

        if (m_nHead + nLen <= MAX_LEN )
        {
            m_nHead    = (m_nHead + nLen) % MAX_LEN;
        }
        else
        {
            m_nHead = nLen - (MAX_LEN - m_nHead);
        }

        return true;
    }

public:
    T    m_Buffer[MAX_LEN];    // 数据区
private:

    unsigned int    m_nHead;                        // 队头
    unsigned int    m_nTail;                        // 队尾

};

#endif
时间: 2024-08-05 21:14:12

无锁的环形队列的相关文章

并发无锁之环形队列生产者消费者问题

1.生产者消费者问题 三种关系:生产者--生产者(互斥):消费者-消费者(互斥):生产者--消费者(互斥同步) 两个角色:生产者:消费者 一种生产场所:缓冲区 2.环形队列(缓冲区) 数据结构:可以有多种,这里选用数组,逻辑上将a[0]和a[size-1]相连构成环形队列 判断空/判断满:当读指针和写指针指向同一个区域为空,或者满(但不能区分空或者满) 两种方案:1.即尾结点与首结点之间至少留有一个元素的空间. 2. 添加一个计数器(信号量就是计数器所以这里用信号量完成计数器的功能) 3.sem

环形无锁队列

环形无锁队列 Table of Contents 1 环形无锁队列的实现 2 死锁及饥饿 3 一些优化 1 环形无锁队列的实现 数据结构定义: template class LockFreeQueue { private: ElementT *mArray; int mCapacity; int mFront; int mTail; } 由于出队操作是在队首进行,入队操作是在队尾进行,因此,我们可以尝试用mFront和mTail来实现多个线程之间的协调.这其中会用到CAS操作: 入队操作伪码:

无锁队列的环形数组实现

对无锁队列的最初兴趣来自梁斌同志的一个英雄帖:http://coderpk.com/. 第一次看到这个题目的时候还不知道CAS,FAA等所谓的“原子操作”,但直觉上感觉,通过对读写操作的性能优化来达到大幅提高队列性能的方法是行不通的,就算读写操作全用汇编来写,也不会和正常的read及 write有数量级上的区别.后来搜索了一下lock free data structure,才知道了关于原子操作的一些东西,同时也纠正了自己由来已久的一个错误观点:C++中的++操作和--操作都不是原子操作.这篇笔

无锁环形队列

1 #include "stdafx.h" 2 #include <process.h> 3 #include <stdio.h> 4 #include <Windows.h> 5 #include <stdlib.h> 6 #include <assert.h> 7 8 #define MAX_VIDEO_BUFF 1024 9 10 struct Header 11 { 12 WORD wSize; 13 char dat

使用无锁队列(环形缓冲区)注意事项

环形缓冲区是生产者和消费者模型中常用的数据结构.生产者将数据放入数组的尾端,而消费者从数组的另一端移走数据,当达到数组的尾部时,生产者绕回到数组的头部.如果只有一个生产者和一个消费者,那么就可以做到免锁访问环形缓冲区(Ring Buffer).写入索引只允许生产者访问并修改,只要写入者在更新索引之前将新的值保存到缓冲区中,则读者将始终看到一致的数据结构.同理,读取索引也只允许消费者访问并修改. 环形缓冲区实现原理图 如图所示,当读者和写者指针相等时,表明缓冲区是空的,而只要写入指针在读取指针后面

眉目传情之并发无锁环形队列的实现

眉目传情之并发无锁环形队列的实现 Author:Echo Chen(陈斌) Email:[email protected] Blog:Blog.csdn.net/chen19870707 Date:October 10th, 2014 前面在<眉目传情之匠心独运的kfifo>一文中详细解析了 linux  内核并发无锁环形队列kfifo的原理和实现,kfifo鬼斧神工,博大精深,让人叹为观止,但遗憾的是kfifo为内核提供服务,并未开放出来.剑不试则利钝暗,弓不试则劲挠诬,鹰不试则巧拙惑,马不

生产者消费者模式下的并发无锁环形缓冲区

上一篇记录了几种环形缓冲区的设计方法和环形缓冲区在生产者消费者模式下的使用(并发有锁),这一篇主要看看怎么实现并发无锁. 0.简单的说明 首先对环形缓冲区做下说明: 环形缓冲区使用改进的数组版本,缓冲区容量为2的幂 缓冲区满阻塞生产者,消费者进行消费后,缓冲区又有可用资源,由消费者唤醒生产者 缓冲区空阻塞消费者,生产者进程生产后,缓冲区又有可用资源,由生产者唤醒消费者 然后对涉及到的几个技术做下说明: ⑴CAS,Compare & Set,X86下对应的是CMPXCHG 汇编指令,原子操作,基本

环形缓冲区的设计及其在生产者消费者模式下的使用(并发有锁环形队列)

1.环形缓冲区 缓冲区的好处,就是空间换时间和协调快慢线程.缓冲区可以用很多设计法,这里说一下环形缓冲区的几种设计方案,可以看成是几种环形缓冲区的模式.设计环形缓冲区涉及到几个点,一是超出缓冲区大小的的索引如何处理,二是如何表示缓冲区满和缓冲区空,三是如何入队.出队,四是缓冲区中数据长度如何计算. ps.规定以下所有方案,在缓冲区满时不可再写入数据,缓冲区空时不能读数据 1.1.常规数组环形缓冲区 设缓冲区大小为N,队头out,队尾in,out.in均是下标表示: 初始时,in=out=0 队头

boost 无锁队列

一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久违的Boost.Lockfree模块,本着学习的心态,将其翻译如下.(原文地址:http://www.boost.org/doc/libs/1_53_0/doc/html/lockfree.html) Chapter 17. Boost.Lockfree 第17章.Boost.Lockfree Ta