1. 优化HRingBuffer, 更改为kfifo设计方法
This commit is contained in:
parent
df494faf2d
commit
fa25457c1e
@ -2,6 +2,11 @@
|
||||
* 日期: 2025-04-13
|
||||
* 作者: coffee
|
||||
* 描述: 环转缓冲区
|
||||
*
|
||||
* 设计说明:
|
||||
* start 和 end 只增不减, 利用无符号整数回绕特性计算已用长度。
|
||||
* 满 = (end - start) == len, 空 = end == start
|
||||
* (不需要缓冲区大小为 2 的幂)
|
||||
*/
|
||||
|
||||
#ifndef _H_RING_BUFFER_H_
|
||||
@ -16,9 +21,9 @@ enum eRingBufferFlag {
|
||||
kHRingBufferFlag16 = 0x02, // 数据16位
|
||||
kHRingBufferFlag32 = 0x04, // 数据32位
|
||||
|
||||
kHRingBufferPow2 = 0x08, // 容量为 2 的幂 (可用掩码代替取模)
|
||||
kHRingBufferFlagAllMask = 0x07, // 数据掩码
|
||||
|
||||
kHRingBufferFull = 0x40, // 环转缓冲区满
|
||||
kHRingBufferNeedInit = 0x80, // 需要初始化
|
||||
};
|
||||
|
||||
@ -45,9 +50,9 @@ typedef uint8_t HRingBufferLenType;
|
||||
|
||||
typedef struct __attribute__ ((__packed__)) _HRingBufferBase {
|
||||
volatile uint8_t flag;
|
||||
HRingBufferLenType len;
|
||||
HRingBufferLenType start;
|
||||
HRingBufferLenType end;
|
||||
HRingBufferLenType len; // 容量 (任意值)
|
||||
HRingBufferLenType start; // 只增不减的读指针
|
||||
HRingBufferLenType end; // 只增不减的写指针
|
||||
} _HRingBufferBase;
|
||||
|
||||
|
||||
|
||||
@ -132,6 +132,7 @@ void *HMemCalloc(size_t num, size_t size) {
|
||||
}
|
||||
|
||||
if (num > (SIZE_MAX / size)) {
|
||||
LogD("num[%d] overflow", num);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -150,6 +151,7 @@ void *HMemRealloc(void *ptr, size_t size) {
|
||||
}
|
||||
|
||||
if (size > HMEM_SIZE_MAX) {
|
||||
LogD("size[%d] overflow", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -213,6 +215,7 @@ uint8_t HMemFree(void *ptr) {
|
||||
|
||||
HMemHeader *header = GetHeader(ptr);
|
||||
if (!IsValidHeader(header)) {
|
||||
LogD("invalid addr[0x%08x]", ptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -241,6 +244,8 @@ void *HMemAddRef(void *ptr, size_t size) {
|
||||
if (IsValidHeader(header)) {
|
||||
if (header->refCount < HMEM_REFCOUNT_MAX) {
|
||||
++header->refCount;
|
||||
} else {
|
||||
LogD("ref count[%d][%d] overflow", header->refCount, HMEM_REFCOUNT_MAX);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
#include <HRingBuffer.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -14,6 +12,19 @@
|
||||
#endif
|
||||
|
||||
|
||||
// 已用长度: 强转回 HRingBufferLenType 避免整型提升 (uint16_t→int) 导致负值
|
||||
#define HRING_USED(end, start) ((HRingBufferLenType)((end) - (start)))
|
||||
|
||||
// 数组下标: 2 次幂走掩码, 否则取模
|
||||
static inline HRingBufferLenType HRingIndex(HRingBufferLenType ptr, HRingBufferLenType len, uint8_t flag) {
|
||||
if (flag & kHRingBufferPow2) {
|
||||
return ptr & (len - 1);
|
||||
}
|
||||
|
||||
return ptr % len;
|
||||
}
|
||||
|
||||
|
||||
static inline void InitRingBuffer(HRingBufferType *ringBuffer) {
|
||||
if (ringBuffer == NULL) {
|
||||
LogD("RingBuffer is NULL");
|
||||
@ -32,6 +43,11 @@ static inline void InitRingBuffer(HRingBufferType *ringBuffer) {
|
||||
base->start = _HRING_BUFFER_INIT_SIZE_INIT(len);
|
||||
len = (uint8_t *)&base->end;
|
||||
base->end = _HRING_BUFFER_INIT_SIZE_INIT(len);
|
||||
|
||||
// 检测容量是否为 2 的幂
|
||||
if (base->len != 0 && (base->len & (base->len - 1)) == 0) {
|
||||
base->flag |= kHRingBufferPow2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t GetRingBufferType(const HRingBufferType *ringBuffer) {
|
||||
@ -93,33 +109,16 @@ static inline void SetRingBufferData(HRingBufferType *ringBuffer, HRingBufferLen
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t IsRingBufferFull(const HRingBufferType *ringBuffer) {
|
||||
if (ringBuffer == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
InitRingBuffer((HRingBufferType *)ringBuffer);
|
||||
const _HRingBufferBase *base = (const _HRingBufferBase *)ringBuffer;
|
||||
return !!(base->flag & kHRingBufferFull);
|
||||
}
|
||||
|
||||
static inline void SetRingBufferFull(HRingBufferType *ringBuffer, uint8_t full) {
|
||||
InitRingBuffer((HRingBufferType *)ringBuffer);
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)ringBuffer;
|
||||
const uint8_t f = -(uint8_t)(!!full);
|
||||
base->flag = (base->flag & ~kHRingBufferFull) | (f & kHRingBufferFull);
|
||||
}
|
||||
|
||||
static void AdjustReadPos(HRingBufferType *ringBuffer, HRingBufferLenType pos) {
|
||||
const uint8_t isFull = IsRingBufferFull(ringBuffer);
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)ringBuffer;
|
||||
base->start += pos;
|
||||
base->start -= (base->start >= base->len) * base->len;
|
||||
if (isFull) {
|
||||
SetRingBufferFull(ringBuffer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* 公开接口 — kfifo 风格单调指针
|
||||
*
|
||||
* 核心变化:
|
||||
* - start/end 只增不减, 不再做 wrap 取模
|
||||
* - 已用长度 = end - start (无符号回绕保证正确)
|
||||
* - 满 = (end - start) == len, 空 = end == start
|
||||
* - 数组下标: 容量为 2 次幂时走 & (len-1), 否则 %
|
||||
* ========================================================================== */
|
||||
HRingBufferLenType HRingbufferInit8(void *buffer, HRingBufferLenType size)
|
||||
{
|
||||
const int len = size - sizeof(_HRingBufferBase);
|
||||
@ -129,10 +128,16 @@ HRingBufferLenType HRingbufferInit8(void *buffer, HRingBufferLenType size)
|
||||
|
||||
const uint8_t init[] = _HRING_BUFFER_INIT8(len);
|
||||
memcpy(buffer, init, sizeof(init));
|
||||
|
||||
// 运行时检测 2 次幂并标记
|
||||
if (len != 0 && ((HRingBufferLenType)len & ((HRingBufferLenType)len - 1)) == 0) {
|
||||
((_HRingBufferBase *)buffer)->flag |= kHRingBufferPow2;
|
||||
}
|
||||
|
||||
return HRingBufferGetLen((HRingBufferType *)buffer);
|
||||
}
|
||||
|
||||
// 添加数据到环形缓冲区, 成功返回1, 失败返回0
|
||||
|
||||
uint8_t HRingBufferAddData(HRingBufferType* buffer, HRingBufferDataType data) {
|
||||
if (buffer == NULL) {
|
||||
return 0;
|
||||
@ -145,68 +150,66 @@ uint8_t HRingBufferAddData(HRingBufferType* buffer, HRingBufferDataType data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 判断缓冲区是否已满
|
||||
if (IsRingBufferFull(buffer)) {
|
||||
LogD("buffer is full, len[%d], start[%d], end[%d]", base->len, base->start, base->end);
|
||||
if (HRING_USED(base->end, base->start) == base->len) {
|
||||
LogD("buffer is full");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetRingBufferData(buffer, base->end, data);
|
||||
SetRingBufferData(buffer, HRingIndex(base->end, base->len, base->flag), data);
|
||||
++base->end;
|
||||
base->end -= (base->end >= base->len) * base->len;
|
||||
|
||||
if (base->end == base->start) {
|
||||
SetRingBufferFull(buffer, 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 添加数据到环形缓冲区, 当环形缓冲区满时, 会覆盖旧数据, 成功返回1, 失败返回0
|
||||
|
||||
uint8_t HRingBufferAddDataOver(HRingBufferType* buffer, HRingBufferDataType data) {
|
||||
if (IsRingBufferFull(buffer)) {
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
++base->start;
|
||||
base->start -= (base->start >= base->len) * base->len;
|
||||
SetRingBufferFull(buffer, 0);
|
||||
if (buffer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HRingBufferAddData(buffer, data);
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
InitRingBuffer(buffer);
|
||||
if (base->len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HRING_USED(base->end, base->start) == base->len) {
|
||||
++base->start;
|
||||
}
|
||||
|
||||
SetRingBufferData(buffer, HRingIndex(base->end, base->len, base->flag), data);
|
||||
++base->end;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 获取指定位置的环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR
|
||||
|
||||
HRingBufferDataType HRingBufferGetData(HRingBufferType* buffer, HRingBufferLenType index) {
|
||||
if (buffer == NULL) {
|
||||
return HRING_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
if (HRingBufferGetUseLen(buffer) <= index) {
|
||||
LogD("error index[%d], len[%d]", index, HRingBufferGetLen(buffer));
|
||||
LogD("error index");
|
||||
return HRING_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
return GetRingBufferData(buffer, (base->start + index) % base->len);
|
||||
return GetRingBufferData(buffer, HRingIndex(base->start + index, base->len, base->flag));
|
||||
}
|
||||
|
||||
// 获取环形缓冲区数据, 失败返回 HRING_BUFFER_ERROR
|
||||
|
||||
HRingBufferDataType HRingBufferPopData(HRingBufferType* buffer) {
|
||||
if (HRingBufferGetUseLen(buffer) == 0) {
|
||||
return HRING_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
HRingBufferDataType data = GetRingBufferData(buffer, base->start);
|
||||
const HRingBufferDataType data = GetRingBufferData(buffer, HRingIndex(base->start, base->len, base->flag));
|
||||
++base->start;
|
||||
base->start -= (base->start >= base->len) * base->len;
|
||||
if (IsRingBufferFull(buffer)) {
|
||||
SetRingBufferFull(buffer, 0);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// 获取环状缓冲区数据, 返回获取的数据长度
|
||||
|
||||
HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *data, HRingBufferLenType len)
|
||||
{
|
||||
const HRingBufferLenType useLen = HRingBufferGetUseLen(buffer);
|
||||
@ -229,7 +232,9 @@ HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *dat
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HRingBufferLenType startPos = base->start;
|
||||
// 当前读位置数组下标
|
||||
const HRingBufferLenType startPos = HRingIndex(base->start, base->len, base->flag);
|
||||
// 第一段: 从 startPos 到缓冲区末尾
|
||||
HRingBufferLenType firstCopyElems = base->len - startPos;
|
||||
if (firstCopyElems > copyElems) {
|
||||
firstCopyElems = copyElems;
|
||||
@ -242,11 +247,11 @@ HRingBufferLenType HRingBufferGetByteDatas(HRingBufferType* buffer, uint8_t *dat
|
||||
memcpy(data + firstCopyLen, GetRingByteData(buffer, 0), copyLen - firstCopyLen);
|
||||
}
|
||||
|
||||
AdjustReadPos(buffer, copyElems);
|
||||
base->start += copyElems;
|
||||
return copyLen;
|
||||
}
|
||||
|
||||
// 获取环形缓冲区数据长度
|
||||
|
||||
HRingBufferLenType HRingBufferGetUseLen(HRingBufferType* buffer) {
|
||||
if (buffer == NULL) {
|
||||
return 0;
|
||||
@ -254,22 +259,15 @@ HRingBufferLenType HRingBufferGetUseLen(HRingBufferType* buffer) {
|
||||
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
InitRingBuffer(buffer);
|
||||
if (base->end >= base->start) {
|
||||
if (IsRingBufferFull(buffer)) {
|
||||
return base->len;
|
||||
}
|
||||
|
||||
return base->end - base->start;
|
||||
}
|
||||
|
||||
return base->len - base->start + base->end;
|
||||
return HRING_USED(base->end, base->start);
|
||||
}
|
||||
|
||||
// 获取环形缓冲区数据字节长度
|
||||
|
||||
HRingBufferLenType HRingBufferGetUseByteLen(HRingBufferType* buffer) {
|
||||
return HRingBufferGetUseLen(buffer) * GetRingBufferTypeSize(buffer);
|
||||
}
|
||||
|
||||
|
||||
HRingBufferLenType HRingBufferGetLen(HRingBufferType* buffer) {
|
||||
if (buffer == NULL) {
|
||||
return 0;
|
||||
@ -280,7 +278,7 @@ HRingBufferLenType HRingBufferGetLen(HRingBufferType* buffer) {
|
||||
return base->len;
|
||||
}
|
||||
|
||||
// 清空环形缓冲区
|
||||
|
||||
void HRingBufferClear(HRingBufferType* buffer) {
|
||||
if (buffer == NULL) {
|
||||
return ;
|
||||
@ -288,20 +286,27 @@ void HRingBufferClear(HRingBufferType* buffer) {
|
||||
|
||||
_HRingBufferBase *base = (_HRingBufferBase *)buffer;
|
||||
InitRingBuffer(buffer);
|
||||
SetRingBufferFull(buffer, 0);
|
||||
base->start = 0;
|
||||
base->end = 0;
|
||||
}
|
||||
|
||||
// 判断环形缓冲区是否为空
|
||||
|
||||
uint8_t HRingBufferEmpty(HRingBufferType* buffer) {
|
||||
return HRingBufferGetUseLen(buffer) == 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t HRingBufferFull(HRingBufferType* buffer) {
|
||||
return IsRingBufferFull(buffer);
|
||||
if (buffer == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
InitRingBuffer(buffer);
|
||||
const _HRingBufferBase *base = (const _HRingBufferBase *)buffer;
|
||||
return HRING_USED(base->end, base->start) == base->len;
|
||||
}
|
||||
|
||||
|
||||
uint8_t HRingBufferExist(HRingBufferType* buffer, HRingBufferDataType data) {
|
||||
const HRingBufferLenType len = HRingBufferGetUseLen(buffer);
|
||||
for (HRingBufferLenType i = 0; i < len; ++i) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user