单向循环链表实现RingBuffer

Posted fulianzhou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单向循环链表实现RingBuffer相关的知识,希望对你有一定的参考价值。

        一般我们用的RingBuffer都是用数组或vector实现,用读指针与写指针来控制RingBuffer的输入与输出。用不同的线程来Push与Pull,一般情况下这种结构是非常高效的,无需加锁。但是当Pull处理线程比Push处理线程慢得多的时候,Push就会等待RingBuffer非空;等待有时候会很耗费时间,运行的越久累积的时延就越高。

        所以用单向循环链表来替代数组或vector,当RingBuffer满时就插入一个新的位置,减少Push等待时间。但是如果Pull处理的时间太长,Push又不断有新数据插入,就会导致RingBuffer太长,占用过多资源,所以可以加一个计数器来控制RingBuffer的最大长度。

listringbuffer.h

#ifndef _LIST_RINGBUFFER_H_
#define _LIST_RINGBUFFER_H_
#include <stdint.h>


template <typename T>
struct LNode

    T data;
    LNode* next;

    LNode() :next(NULL)
    LNode(const T& item) : next(NULL), data(item)
;

template <typename T>
class ListRingBuffer

private:
    uint32_t m_cap;
    LNode<T>* m_root;
    LNode<T>* m_posr;
    LNode<T>* m_posw;
public:
    ListRingBuffer(int initsize = 10)
        : m_root(NULL),
        m_posr(NULL),
        m_posw(NULL),
        m_cap(initsize)
    
        if (initsize < 10)
        
            initsize = 10;
            m_cap = initsize;
        

        m_root = new LNode<T>;
        //m_root->data = -1;

        LNode<T>* pTail = m_root;

        for (int i = 0; i < initsize; i++)
        
            LNode<T>* pNode = new LNode<T>;
            //pNode->data = -1;
            pNode->next = m_root;
            m_root = pNode;
        

        m_posr = m_posw = m_root;
        pTail->next = m_root;
    

    ~ListRingBuffer()
    
        while (m_root)
        
            LNode<T>* pNode = m_root;
            m_root = m_root->next;

            if (pNode)
            
                delete pNode;
                pNode = NULL;
            
        
    

public:
    int GetCap()  return m_cap; 

    void Push(const T &data)
    
        /* buffer is full */
        if (m_posw->next == m_posr)
        
            m_posw->data = data;

            LNode<T>* pNode = new LNode<T>;
            //pNode->data = -1;
            pNode->next = m_posw->next;
            m_posw->next = pNode;

            m_posw = m_posw->next;
            m_cap += 1;
            printf("");
            //printf("cap = %d\\n", m_cap);
        
        else
        
            m_posw->data = data;
            m_posw = m_posw->next;
        
    

    bool Pull(T& data)
    
        if (m_posr == m_posw)
        
            return false;
        

        data = m_posr->data;
        m_posr = m_posr->next;

        return true;
    
;
#endif

main.cpp

#include <stdio.h>
#include <Windows.h>

#include "listringbuffer.h"


DWORD WINAPI PushThread(LPVOID lpParam)

    ListRingBuffer<int>* pbuff = (ListRingBuffer<int>*)lpParam;
    if (!pbuff)
    
        return -1;
    

    int counter = 1;
    while (true)
    
        pbuff->Push(counter);
        counter++;

        //pbuff->Travel();
        Sleep(1);
    

    return 0;


DWORD WINAPI PullThread(LPVOID lpParam)

    ListRingBuffer<int>* pbuff = (ListRingBuffer<int>*)lpParam;
    if (!pbuff)
    
        return -1;
    

    int idx = 1;
    while (true)
    
        int data = 0;
        if (!pbuff->Pull(data))
        
            continue;
        
        printf("idx = %d data=%d cap=%d\\n", idx, data, pbuff->GetCap());

        if (idx != data)
        
            break;
        

        idx++;
    

    return 0;



int main(int argc, char* argv[])

    ListRingBuffer<int> listbuffer;

    HANDLE handles[2] =  NULL ;

    DWORD dwPid;
    handles[0] = CreateThread(NULL, 0, PushThread, &listbuffer, 0, &dwPid);
    if (!handles[0])
    
        printf("create push thread failed, errno:%s\\n", GetLastError());
    

    handles[1] = CreateThread(NULL, 0, PullThread, &listbuffer, 0, &dwPid);
    if (!handles[1])
    
        printf("create push thread failed, errno:%s\\n", GetLastError());
    

    WaitForMultipleObjects(2, handles, TRUE, INFINITE);

    return 0;



 

以上是关于单向循环链表实现RingBuffer的主要内容,如果未能解决你的问题,请参考以下文章

单向循环链表实现RingBuffer

(java实现)单向循环链表

单向循环链表

java实现单向循环链表

单向循环链表

单向循环链表实现