|
分享源码
界面截图: |
- |
是否带模块: |
- |
备注说明: |
- |
本帖最后由 Jy倾恋 于 2021-5-16 14:22 编辑
这个环形缓冲区是基于 http://circularbuffer.codeplex.com/、 http://en.wikipedia.org/wiki/Circular_buffer 修改的
最近自己项目用到的一个缓冲区,理论上支持多线程
在自己的多线程项目测试过,暂时没有问题
下面科普下环形缓冲区在内存里的变化:
环形缓冲区首先从空开始并具有设置的长度;在下图中,是一个7字节的缓冲区:
假设在环形缓冲区的中心写入1(确切的起始位置在环形缓冲区中并不重要):
然后,假设将另外两个字节(2&3)添加到环形缓冲区,它们将放在1之后:
如果删除了两个字节,则环形缓冲区内部的两个最早加入的值将被删除。 环形缓冲区使用FIFO(先进先出)逻辑。 在示例1和2中,第一个进入“环形缓冲区”则第一个被移除,而将3留在缓冲区中。
如果缓冲区有7个字节,则它已经完全占满:
环形缓冲区的一个特性是,当缓冲区已满并执行后续写入操作时,它将开始覆盖最早的数据。 在当前示例中,添加了两个元素A和B并覆盖了3和4:
最后,如果现在删除了两个字节,则返回的不是3&4而是5&6,因为A&B覆盖了3&4,产生了带有以下内容的缓冲区:
环形缓冲区使用说明:
环形缓冲区的特性是,在使用环形缓冲区时,不会导致内部数据乱七八糟。 (如果使用了非环形缓冲区,那么在没取一个字节时,就必须对所有字节进行移位。)换句话说,环形缓冲区非常适合作为FIFO(先进先出)缓冲区,而标准缓冲区则适合用作FIFO(先进先出)缓冲区。非环形缓冲区非常适合用作LIFO(后进先出)缓冲区。
对于具有固定最大大小的队列,使用环形缓冲是一种很好的实现策略。如果队列采用最大大小,则环形缓冲区是完全理想的实现;所有队列操作都是固定时间。但是,扩展循环缓冲区需要转移存储器,这是非常耗时和消耗资源的。对于任意扩展的队列,可以首选使用链表方法。
这个是24个字节的环形缓冲区
当写指针即将到达读指针时(由于微处理器没有响应),缓冲区停止记录击键。 在某些计算机上会发出哔声。
这个排版真累人- .-
如果有什么BUG,请自行修复
2021/5/16 源码更新:
[+] 为了大家方便理解新增了Demo
2021/5/15 源码更新:
[!] 修复致命BUG,受影响函数:CircularBufferGetBytes、CircularBufferGetBytesFoIndex、CircularBufferPutToMem、CircularBufferPutBytes
下面为更新后代码: |
CircularBufferPutToMem | 整数型 | | |
lp | 整数型 | | | | pData | 整数型 | | | | Index | 整数型 | | | | count | 整数型 | | | |
变量名 | 类 型 | 静态 | 数组 | 备 注 | buffer | CIRCULARBUFFER_STREAM | | | pOld | 整数型 | | | srcIndex | 整数型 | | | bytesToProcess | 整数型 | | | chunk | 整数型 | | | 如果真 (count ≤ 0 )调试输出 (“计数必须为正。”)返回 (0 )pOld = _SWAP_CIRCULARBUFFER_STREAM (buffer, lp)如果真 (buffer.Size + count > buffer.Capacity )调试输出 (“缓冲区没有足够的容量来放置新项目。”)_SWAP_CIRCULARBUFFER_STREAM (buffer, pOld )返回 (0 )InterlockedIncrement (buffer.ref)srcIndex = Index bytesToProcess = count 判断循环首 (bytesToProcess > 0 )chunk = 取较小值 (buffer.Capacity - buffer.Tail, bytesToProcess )RtlMoveMemory (buffer.pBuffer + buffer.Tail, pData + srcIndex, chunk )判断 (buffer.Tail + chunk = buffer.Capacity )InterlockedExchange (buffer.Tail, 0 )InterlockedExchangeAdd (buffer.Tail, chunk )InterlockedExchangeAdd (buffer.Size, chunk)srcIndex = srcIndex + chunk bytesToProcess = bytesToProcess - chunk 判断循环尾 ()CircularBufferFree (lp )_SWAP_CIRCULARBUFFER_STREAM (buffer, pOld )返回 (count )|
CircularBufferGetBytesFoIndex | 字节集 | | |
lp | 整数型 | | | | Index | 整数型 | | | | count | 整数型 | | | |
变量名 | 类 型 | 静态 | 数组 | 备 注 | buffer | CIRCULARBUFFER_STREAM | | | pOld | 整数型 | | | bytesCopied | 整数型 | | | dstIndex | 整数型 | | | chunk | 整数型 | | | arybyte | 字节集 | | | pData | 整数型 | | | 如果真 (Index < 0 )调试输出 (“指定偏移量必须为正 ”)返回 ({ })如果真 (count < 0 )调试输出 (“指定的长度必须为正。”)返回 ({ })pOld = _SWAP_CIRCULARBUFFER_STREAM (buffer, lp)如果真 (count > buffer.Size )调试输出 (“环形缓冲区的内容不足以进行读取/读取操作。”)_SWAP_CIRCULARBUFFER_STREAM (buffer, pOld )返回 ({ })InterlockedIncrement (buffer.ref)bytesCopied = 0 dstIndex = Index arybyte = 取空白字节集 (count )pData = 取指针_字节集型 (arybyte )判断循环首 (count > 0 )chunk = 取较小值 (buffer.Capacity - buffer.Head, count )RtlMoveMemory (pData + dstIndex, buffer.pBuffer + buffer.Head, chunk )判断 (buffer.Head + chunk = buffer.Capacity )InterlockedExchange (buffer.Head, 0 )InterlockedExchangeAdd (buffer.Head, chunk )InterlockedExchangeAdd (buffer.Size, -chunk)dstIndex = dstIndex + chunk bytesCopied = bytesCopied + chunk count = count - chunk 判断循环尾 ()CircularBufferFree (lp )_SWAP_CIRCULARBUFFER_STREAM (buffer, pOld )返回 (arybyte )
源码回复可见,不喜勿喷
CircularBuffer.rar
(340.88 KB, 下载次数: 111)
|
评分
-
参与人数 10 | 好评 +7 |
精币 +18 |
收起
理由
|
fjgh
| + 1 |
+ 2 |
支持开源~!感谢分享 |
木小果
| |
+ 3 |
支持开源~!感谢分享 |
BUG508
| + 1 |
+ 2 |
感谢大佬开源,这个环形缓冲区是真的好用,新技能已get√ |
AI优
| |
+ 1 |
支持开源~!感谢分享 |
小言T默默
| |
+ 2 |
支持开源~!感谢分享 |
哆啦恶梦
| + 1 |
+ 2 |
感谢分享,很给力!~ |
司徒西
| + 1 |
+ 2 |
支持开源~!感谢分享 |
广二爷xxoo
| + 1 |
|
此处应该有鼓励~ |
吃泡面加不起蛋
| + 1 |
+ 1 |
显示日志也用到这个,一共500个日志,循环更新 |
易语言资源网
| + 1 |
+ 3 |
支持开源~!感谢分享 |
查看全部评分
|