单向循环链表实现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的主要内容,如果未能解决你的问题,请参考以下文章