From fa25457c1e43acb461abfa7f32586bca4e721c1e Mon Sep 17 00:00:00 2001 From: coffee Date: Fri, 22 May 2026 00:26:36 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E4=BC=98=E5=8C=96HRingBuffer,=20=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E4=B8=BAkfifo=E8=AE=BE=E8=AE=A1=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/HRingBuffer.h | 13 ++-- src/HMem.c | 5 ++ src/HRingBuffer.c | 151 ++++++++++++++++++++++-------------------- 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/include/HRingBuffer.h b/include/HRingBuffer.h index 518b16b..1e6b019 100644 --- a/include/HRingBuffer.h +++ b/include/HRingBuffer.h @@ -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; diff --git a/src/HMem.c b/src/HMem.c index 915925a..346367a 100644 --- a/src/HMem.c +++ b/src/HMem.c @@ -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; } diff --git a/src/HRingBuffer.c b/src/HRingBuffer.c index 27c0683..38b4bb2 100644 --- a/src/HRingBuffer.c +++ b/src/HRingBuffer.c @@ -1,5 +1,3 @@ - - #include #include @@ -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) {