|
|
|
@ -61,20 +61,52 @@ |
|
|
|
*/ |
|
|
|
void rd_RingbufferInit(rd_ringbuf_t *rb, char *pool, int size) |
|
|
|
{ |
|
|
|
if(NULL == rb || NULL == pool || size <= 0) |
|
|
|
{ |
|
|
|
if (!rb || !pool || size <= 0) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* initialize read and write index */ |
|
|
|
rb->m_bReadMirror = rb->m_sReadIndex = 0; |
|
|
|
rb->m_bWriteMirror = rb->m_sWriteIndex = 0; |
|
|
|
/* 原子方式初始化索引与镜像位 */ |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_bReadMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
/* set buffer pool and size */ |
|
|
|
rb->m_pcBufPtr = pool; |
|
|
|
rb->m_iBufsize = RD_ALIGN_DOWN(size, RD_ALIGN_SIZE); |
|
|
|
} |
|
|
|
|
|
|
|
/* 计算可写空间(原子读取索引) */ |
|
|
|
int rd_RingbufferSpaceLen(rd_ringbuf_t *rb) |
|
|
|
{ |
|
|
|
if (!rb) return -1; |
|
|
|
|
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
if (wb == rb_m) { |
|
|
|
return rb->m_iBufsize - (wi - ri); |
|
|
|
} else { |
|
|
|
return ri - wi; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* 获取环形缓冲区状态(读/写索引) */ |
|
|
|
static enum ERingBufState rd_RingbufferStatus(rd_ringbuf_t *rb) |
|
|
|
{ |
|
|
|
if (!rb) return RINGBUFFER_EMPTY; |
|
|
|
|
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
if (wi == ri) { |
|
|
|
return (wb == rb_m) ? RINGBUFFER_EMPTY : RINGBUFFER_FULL; |
|
|
|
} |
|
|
|
return RINGBUFFER_HALFFULL; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Put a block of data into the ring buffer. If the capacity of ring buffer is insufficient, it will discard out-of-range data. |
|
|
|
* |
|
|
|
@ -86,49 +118,29 @@ void rd_RingbufferInit(rd_ringbuf_t *rb, char *pool, int size) |
|
|
|
*/ |
|
|
|
int rd_RingbufferPut(rd_ringbuf_t *rb, const char *ptr, int length) |
|
|
|
{ |
|
|
|
int size = 0; |
|
|
|
|
|
|
|
if(NULL == rb || NULL == ptr || length <= 0) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
if (!rb || !ptr || length <= 0) return RD_INVALUE; |
|
|
|
|
|
|
|
/* whether has enough space */ |
|
|
|
size = rd_RingbufferSpaceLen(rb); |
|
|
|
int space = rd_RingbufferSpaceLen(rb); |
|
|
|
if (space == 0) return 0; |
|
|
|
if (space < length) length = space; |
|
|
|
|
|
|
|
/* no space */ |
|
|
|
if (size == 0) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
/* drop some data */ |
|
|
|
if (size < length) |
|
|
|
{ |
|
|
|
length = size; |
|
|
|
/* 写入不跨越尾部 */ |
|
|
|
if (rb->m_iBufsize - wi > length) { |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[wi], ptr, length); |
|
|
|
wi += length; |
|
|
|
} else { |
|
|
|
int first = rb->m_iBufsize - wi; |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[wi], ptr, first); |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[0], ptr + first, length - first); |
|
|
|
wb ^= 1; /* 翻转镜像位 */ |
|
|
|
wi = length - first; |
|
|
|
} |
|
|
|
|
|
|
|
if (rb->m_iBufsize - rb->m_sWriteIndex > length) |
|
|
|
{ |
|
|
|
/* m_sReadIndex - m_sWriteIndex = empty space */ |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[rb->m_sWriteIndex], ptr, length); |
|
|
|
/* this should not cause overflow because there is enough space for
|
|
|
|
* length of data in current mirror */ |
|
|
|
rb->m_sWriteIndex += length; |
|
|
|
return length; |
|
|
|
} |
|
|
|
|
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[rb->m_sWriteIndex], |
|
|
|
&ptr[0], |
|
|
|
rb->m_iBufsize - rb->m_sWriteIndex); |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[0], |
|
|
|
&ptr[rb->m_iBufsize - rb->m_sWriteIndex], |
|
|
|
length - (rb->m_iBufsize - rb->m_sWriteIndex)); |
|
|
|
|
|
|
|
/* we are going into the other side of the mirror */ |
|
|
|
rb->m_bWriteMirror ^= 1; |
|
|
|
rb->m_sWriteIndex = length - (rb->m_iBufsize - rb->m_sWriteIndex); |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, wb, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return length; |
|
|
|
} |
|
|
|
|
|
|
|
@ -143,53 +155,38 @@ int rd_RingbufferPut(rd_ringbuf_t *rb, const char *ptr, int length) |
|
|
|
*/ |
|
|
|
int rd_RingbufferPutForce(rd_ringbuf_t *rb, const char *ptr, int length) |
|
|
|
{ |
|
|
|
int space_length; |
|
|
|
|
|
|
|
if (NULL == rb || NULL == ptr || length <= 0) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
if (!rb || !ptr || length <= 0) return RD_INVALUE; |
|
|
|
|
|
|
|
space_length = rd_RingbufferSpaceLen(rb); |
|
|
|
|
|
|
|
if (length > rb->m_iBufsize) |
|
|
|
{ |
|
|
|
ptr = &ptr[length - rb->m_iBufsize]; |
|
|
|
int space = rd_RingbufferSpaceLen(rb); |
|
|
|
if (length > rb->m_iBufsize) { |
|
|
|
ptr += length - rb->m_iBufsize; |
|
|
|
length = rb->m_iBufsize; |
|
|
|
} |
|
|
|
|
|
|
|
if (rb->m_iBufsize - rb->m_sWriteIndex > length) |
|
|
|
{ |
|
|
|
/* m_sReadIndex - m_sWriteIndex = empty space */ |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[rb->m_sWriteIndex], ptr, length); |
|
|
|
/* this should not cause overflow because there is enough space for
|
|
|
|
* length of data in current mirror */ |
|
|
|
rb->m_sWriteIndex += length; |
|
|
|
|
|
|
|
if (length > space_length) |
|
|
|
rb->m_sReadIndex = rb->m_sWriteIndex; |
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
return length; |
|
|
|
if (rb->m_iBufsize - wi > length) { |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[wi], ptr, length); |
|
|
|
wi += length; |
|
|
|
if (length > space) { |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
} |
|
|
|
} else { |
|
|
|
int first = rb->m_iBufsize - wi; |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[wi], ptr, first); |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[0], ptr + first, length - first); |
|
|
|
wb ^= 1; |
|
|
|
wi = length - first; |
|
|
|
if (length > space) { |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
if (wi <= ri) wb ^= 1; |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
} |
|
|
|
|
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[rb->m_sWriteIndex], |
|
|
|
&ptr[0], |
|
|
|
rb->m_iBufsize - rb->m_sWriteIndex); |
|
|
|
RD_MEMCPY(&rb->m_pcBufPtr[0], |
|
|
|
&ptr[rb->m_iBufsize - rb->m_sWriteIndex], |
|
|
|
length - (rb->m_iBufsize - rb->m_sWriteIndex)); |
|
|
|
|
|
|
|
/* we are going into the other side of the mirror */ |
|
|
|
rb->m_bWriteMirror ^= 1; |
|
|
|
rb->m_sWriteIndex = length - (rb->m_iBufsize - rb->m_sWriteIndex); |
|
|
|
|
|
|
|
if (length > space_length) |
|
|
|
{ |
|
|
|
if (rb->m_sWriteIndex <= rb->m_sReadIndex) |
|
|
|
rb->m_bReadMirror ^= 1; |
|
|
|
rb->m_sReadIndex = rb->m_sWriteIndex; |
|
|
|
} |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, wb, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return length; |
|
|
|
} |
|
|
|
|
|
|
|
@ -204,49 +201,28 @@ int rd_RingbufferPutForce(rd_ringbuf_t *rb, const char *ptr, int length) |
|
|
|
*/ |
|
|
|
int rd_RingbufferGet(rd_ringbuf_t *rb, char *ptr, int length) |
|
|
|
{ |
|
|
|
int size; |
|
|
|
|
|
|
|
if (NULL == rb || NULL == ptr || length <= 0) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
if (!rb || !ptr || length <= 0) return RD_INVALUE; |
|
|
|
|
|
|
|
/* whether has enough data */ |
|
|
|
size = rd_RingbufferDataLen(rb); |
|
|
|
int avail = rd_RingbufferDataLen(rb); |
|
|
|
if (avail == 0) return 0; |
|
|
|
if (length > avail) length = avail; |
|
|
|
|
|
|
|
/* no data */ |
|
|
|
if (size == 0) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
/* less data */ |
|
|
|
if (size < length) |
|
|
|
{ |
|
|
|
length = size; |
|
|
|
if (rb->m_iBufsize - ri > length) { |
|
|
|
RD_MEMCPY(ptr, &rb->m_pcBufPtr[ri], length); |
|
|
|
ri += length; |
|
|
|
} else { |
|
|
|
int first = rb->m_iBufsize - ri; |
|
|
|
RD_MEMCPY(ptr, &rb->m_pcBufPtr[ri], first); |
|
|
|
RD_MEMCPY(ptr + first, &rb->m_pcBufPtr[0], length - first); |
|
|
|
rb_m ^= 1; |
|
|
|
ri = length - first; |
|
|
|
} |
|
|
|
|
|
|
|
if (rb->m_iBufsize - rb->m_sReadIndex > length) |
|
|
|
{ |
|
|
|
/* copy all of data */ |
|
|
|
RD_MEMCPY(ptr, &rb->m_pcBufPtr[rb->m_sReadIndex], length); |
|
|
|
/* this should not cause overflow because there is enough space for
|
|
|
|
* length of data in current mirror */ |
|
|
|
rb->m_sReadIndex += length; |
|
|
|
return length; |
|
|
|
} |
|
|
|
|
|
|
|
RD_MEMCPY(&ptr[0], |
|
|
|
&rb->m_pcBufPtr[rb->m_sReadIndex], |
|
|
|
rb->m_iBufsize - rb->m_sReadIndex); |
|
|
|
RD_MEMCPY(&ptr[rb->m_iBufsize - rb->m_sReadIndex], |
|
|
|
&rb->m_pcBufPtr[0], |
|
|
|
length - (rb->m_iBufsize - rb->m_sReadIndex)); |
|
|
|
|
|
|
|
/* we are going into the other side of the mirror */ |
|
|
|
rb->m_bReadMirror ^= 1; |
|
|
|
rb->m_sReadIndex = length - (rb->m_iBufsize - rb->m_sReadIndex); |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, ri, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bReadMirror, rb_m, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return length; |
|
|
|
} |
|
|
|
|
|
|
|
@ -262,38 +238,15 @@ int rd_RingbufferGet(rd_ringbuf_t *rb, char *ptr, int length) |
|
|
|
*/ |
|
|
|
int rd_RingbufferPeak(rd_ringbuf_t *rb, char **ptr) |
|
|
|
{ |
|
|
|
int size; |
|
|
|
|
|
|
|
if (NULL == rb) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
|
|
|
|
if (!rb) return RD_INVALUE; |
|
|
|
*ptr = NULL; |
|
|
|
|
|
|
|
/* whether has enough data */ |
|
|
|
size = rd_RingbufferDataLen(rb); |
|
|
|
int avail = rd_RingbufferDataLen(rb); |
|
|
|
if (avail == 0) return 0; |
|
|
|
|
|
|
|
/* no data */ |
|
|
|
if (size == 0) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
*ptr = &rb->m_pcBufPtr[rb->m_sReadIndex]; |
|
|
|
|
|
|
|
if((int)(rb->m_iBufsize - rb->m_sReadIndex) > size) |
|
|
|
{ |
|
|
|
return size; |
|
|
|
} |
|
|
|
|
|
|
|
size = rb->m_iBufsize - rb->m_sReadIndex; |
|
|
|
|
|
|
|
/* we are going into the other side of the mirror */ |
|
|
|
//rb->m_bReadMirror ^= 1;
|
|
|
|
//rb->m_sReadIndex = 0;
|
|
|
|
|
|
|
|
return size; |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
*ptr = &rb->m_pcBufPtr[ri]; |
|
|
|
return avail; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
@ -306,30 +259,22 @@ int rd_RingbufferPeak(rd_ringbuf_t *rb, char **ptr) |
|
|
|
*/ |
|
|
|
int rd_RingbufferPutchar(rd_ringbuf_t *rb, const char ch) |
|
|
|
{ |
|
|
|
if (NULL == rb) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
if (!rb) return RD_INVALUE; |
|
|
|
if (!rd_RingbufferSpaceLen(rb)) return 0; |
|
|
|
|
|
|
|
/* whether has enough space */ |
|
|
|
if (!rd_RingbufferSpaceLen(rb)) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
rb->m_pcBufPtr[rb->m_sWriteIndex] = ch; |
|
|
|
|
|
|
|
/* flip mirror */ |
|
|
|
if (rb->m_sWriteIndex == rb->m_iBufsize-1) |
|
|
|
{ |
|
|
|
rb->m_bWriteMirror ^= 1; |
|
|
|
rb->m_sWriteIndex = 0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
rb->m_sWriteIndex++; |
|
|
|
rb->m_pcBufPtr[wi] = ch; |
|
|
|
if (wi + 1 == rb->m_iBufsize) { |
|
|
|
wb ^= 1; |
|
|
|
wi = 0; |
|
|
|
} else { |
|
|
|
wi++; |
|
|
|
} |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, wb, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
@ -343,37 +288,31 @@ int rd_RingbufferPutchar(rd_ringbuf_t *rb, const char ch) |
|
|
|
*/ |
|
|
|
int rd_RingbufferPutcharForce(rd_ringbuf_t *rb, const char ch) |
|
|
|
{ |
|
|
|
enum ERingBufState old_state; |
|
|
|
if (!rb) return RD_INVALUE; |
|
|
|
|
|
|
|
if (NULL == rb) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
|
|
|
|
old_state = rd_RingbufferStatus(rb); |
|
|
|
|
|
|
|
rb->m_pcBufPtr[rb->m_sWriteIndex] = ch; |
|
|
|
enum ERingBufState old_state = rd_RingbufferStatus(rb); |
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
/* flip mirror */ |
|
|
|
if (rb->m_sWriteIndex == rb->m_iBufsize-1) |
|
|
|
{ |
|
|
|
rb->m_bWriteMirror ^= 1; |
|
|
|
rb->m_sWriteIndex = 0; |
|
|
|
if (old_state == RINGBUFFER_FULL) |
|
|
|
{ |
|
|
|
rb->m_bReadMirror ^= 1; |
|
|
|
rb->m_sReadIndex = rb->m_sWriteIndex; |
|
|
|
rb->m_pcBufPtr[wi] = ch; |
|
|
|
if (wi + 1 == rb->m_iBufsize) { |
|
|
|
wb ^= 1; |
|
|
|
wi = 0; |
|
|
|
if (old_state == RINGBUFFER_FULL) { |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
rb_m ^= 1; |
|
|
|
ATOMIC_STORE(&rb->m_bReadMirror, rb_m, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
rb->m_sWriteIndex++; |
|
|
|
if (old_state == RINGBUFFER_FULL) |
|
|
|
{ |
|
|
|
rb->m_sReadIndex = rb->m_sWriteIndex; |
|
|
|
} else { |
|
|
|
wi++; |
|
|
|
if (old_state == RINGBUFFER_FULL) { |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, wi, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, wb, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
@ -388,30 +327,22 @@ int rd_RingbufferPutcharForce(rd_ringbuf_t *rb, const char ch) |
|
|
|
*/ |
|
|
|
int rd_RingbufferGetchar(rd_ringbuf_t *rb, char *ch) |
|
|
|
{ |
|
|
|
if (NULL == rb) |
|
|
|
{ |
|
|
|
return RD_INVALUE; |
|
|
|
} |
|
|
|
if (!rb) return RD_INVALUE; |
|
|
|
if (!rd_RingbufferDataLen(rb)) return 0; |
|
|
|
|
|
|
|
/* ringbuffer is empty */ |
|
|
|
if (!rd_RingbufferDataLen(rb)) |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
/* put byte */ |
|
|
|
*ch = rb->m_pcBufPtr[rb->m_sReadIndex]; |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
if (rb->m_sReadIndex == rb->m_iBufsize-1) |
|
|
|
{ |
|
|
|
rb->m_bReadMirror ^= 1; |
|
|
|
rb->m_sReadIndex = 0; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
rb->m_sReadIndex++; |
|
|
|
*ch = rb->m_pcBufPtr[ri]; |
|
|
|
if (ri + 1 == rb->m_iBufsize) { |
|
|
|
rb_m ^= 1; |
|
|
|
ri = 0; |
|
|
|
} else { |
|
|
|
ri++; |
|
|
|
} |
|
|
|
|
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, ri, unsigned short, ATOMIC_ORDER_RELEASE); |
|
|
|
ATOMIC_STORE(&rb->m_bReadMirror, rb_m, unsigned char, ATOMIC_ORDER_RELEASE); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
@ -424,27 +355,22 @@ int rd_RingbufferGetchar(rd_ringbuf_t *rb, char *ch) |
|
|
|
*/ |
|
|
|
int rd_RingbufferDataLen(rd_ringbuf_t *rb) |
|
|
|
{ |
|
|
|
switch (rd_RingbufferStatus(rb)) |
|
|
|
{ |
|
|
|
case RINGBUFFER_EMPTY: |
|
|
|
return 0; |
|
|
|
case RINGBUFFER_FULL: |
|
|
|
return rb->m_iBufsize; |
|
|
|
case RINGBUFFER_HALFFULL: |
|
|
|
default: |
|
|
|
{ |
|
|
|
int wi = rb->m_sWriteIndex, ri = rb->m_sReadIndex; |
|
|
|
|
|
|
|
if (wi > ri) |
|
|
|
{ |
|
|
|
return wi - ri; |
|
|
|
if (!rb) return RD_INVALUE; |
|
|
|
|
|
|
|
unsigned short wi = ATOMIC_LOAD(&rb->m_sWriteIndex, unsigned short, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned short ri = ATOMIC_LOAD(&rb->m_sReadIndex, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
unsigned char wb = ATOMIC_LOAD(&rb->m_bWriteMirror, unsigned char, ATOMIC_ORDER_ACQUIRE); |
|
|
|
unsigned char rb_m = ATOMIC_LOAD(&rb->m_bReadMirror, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
|
|
|
|
if (wi == ri) { |
|
|
|
return (wb == rb_m) ? 0 : rb->m_iBufsize; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
|
|
|
|
if (wb == rb_m) { |
|
|
|
return wi - ri; |
|
|
|
} else { |
|
|
|
return rb->m_iBufsize - (ri - wi); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
@ -454,15 +380,11 @@ int rd_RingbufferDataLen(rd_ringbuf_t *rb) |
|
|
|
*/ |
|
|
|
void rd_RingbufferReset(rd_ringbuf_t *rb) |
|
|
|
{ |
|
|
|
if(NULL == rb) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
rb->m_bReadMirror = 0; |
|
|
|
rb->m_sReadIndex = 0; |
|
|
|
rb->m_bWriteMirror = 0; |
|
|
|
rb->m_sWriteIndex = 0; |
|
|
|
if (!rb) return; |
|
|
|
ATOMIC_STORE(&rb->m_sReadIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_sWriteIndex, 0, unsigned short, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_bReadMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
ATOMIC_STORE(&rb->m_bWriteMirror, 0, unsigned char, ATOMIC_ORDER_RELAXED); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
@ -474,32 +396,19 @@ void rd_RingbufferReset(rd_ringbuf_t *rb) |
|
|
|
*/ |
|
|
|
rd_ringbuf_t *rd_RingbufferCreate(int size) |
|
|
|
{ |
|
|
|
rd_ringbuf_t *rb; |
|
|
|
char *pool; |
|
|
|
|
|
|
|
if (size <= 0) |
|
|
|
{ |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (size <= 0) return NULL; |
|
|
|
size = RD_ALIGN_DOWN(size, RD_ALIGN_SIZE); |
|
|
|
|
|
|
|
rb = (rd_ringbuf_t *)RD_MALLOC(sizeof(rd_ringbuf_t)); |
|
|
|
if (rb == NULL) |
|
|
|
{ |
|
|
|
goto exit; |
|
|
|
} |
|
|
|
rd_ringbuf_t *rb = (rd_ringbuf_t *)RD_MALLOC(sizeof(rd_ringbuf_t)); |
|
|
|
if (!rb) return NULL; |
|
|
|
|
|
|
|
pool = (char *)RD_MALLOC(size); |
|
|
|
if (pool == NULL) |
|
|
|
{ |
|
|
|
char *pool = (char *)RD_MALLOC(size); |
|
|
|
if (!pool) { |
|
|
|
RD_FREE(rb); |
|
|
|
rb = NULL; |
|
|
|
goto exit; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
rd_RingbufferInit(rb, pool, size); |
|
|
|
|
|
|
|
exit: |
|
|
|
rd_RingbufferInit(rb, pool, size); |
|
|
|
return rb; |
|
|
|
} |
|
|
|
|
|
|
|
@ -510,11 +419,7 @@ exit: |
|
|
|
*/ |
|
|
|
void rd_RingbufferDestroy(rd_ringbuf_t *rb) |
|
|
|
{ |
|
|
|
if (NULL == rb) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (!rb) return; |
|
|
|
RD_FREE(rb->m_pcBufPtr); |
|
|
|
RD_FREE(rb); |
|
|
|
} |
|
|
|
|