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