我尝试编写一个非常紧凑的环形缓冲区。缓冲区保存2 ^ X值(X:1-7)我需要的是增加X位(LSB)但保留其余变量。我有一个解决方案,但我不知道这是否有效(从未修改过指针地址)并且它不那么紧凑。知道如何改善这个吗?
// hardcoded ringbuffersize for better ram usage
// this frees us out, start, end, size variables
// 7 == 128, 6 == 64
#define LIGHTWEIGHT_RING_BUFFER_BITS 7
#define LIGHTWEIGHT_RING_BUFFER_SIZE (1<<LIGHTWEIGHT_RING_BUFFER_BITS)
// thatswhy we cant use 256 buffer size
#define LIGHTWEIGHT_RING_BUFFER_DISABLED LIGHTWEIGHT_RING_BUFFER_SIZE+1
// save new data
*Buffer->In = Data;
// save LSB bits
uint8_t pointermask = Buffer->In;
// discard all LSB bits
Buffer->In >>= LIGHTWEIGHT_RING_BUFFER_BITS;
Buffer->In <<= LIGHTWEIGHT_RING_BUFFER_BITS;
// save the LSB bits + 1
Buffer->In |= ++pointermask & (LIGHTWEIGHT_RING_BUFFER_SIZE - 1)
Buffer->Count++;
答案 0 :(得分:0)
这是一个简单的环形缓冲区实现的样子。环形缓冲区的大小由MASK
确定。 MASK
的值必须为2 n -1,其中n <= 8
。对于256字节的环形缓冲区,您可以完全消除掩码。
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#define MASK 7
typedef struct
{
uint8_t head;
uint8_t tail;
uint8_t data[MASK + 1];
}
stRingBuffer;
stRingBuffer ringBuffer = { 0, 0 };
// returns true if successful, false if the ring buffer is full
// the argument is the byte that is to be stored in the buffer
bool WriteToRingBuffer( stRingBuffer *buffer, uint8_t data )
{
uint8_t nextHeadValue = (buffer->head + 1) & MASK;
if ( nextHeadValue == buffer->tail )
return( false );
buffer->data[buffer->head] = data;
buffer->head = nextHeadValue;
return( true );
}
// returns a byte from the ring buffer, or 0 if the buffer is empty
// the caller is responsible for making sure the buffer is not empty before calling this function
uint8_t ReadFromRingBuffer( stRingBuffer *buffer )
{
uint8_t data = 0;
if ( buffer->tail != buffer->head )
{
data = buffer->data[buffer->tail];
buffer->tail = (buffer->tail + 1) & MASK;
}
return( data );
}
// returns the number of items currently in the ring buffer
int itemCountInRingBuffer( stRingBuffer *buffer )
{
return( (buffer->head - buffer->tail) & MASK );
}
int main( void )
{
uint8_t data = 31;
// move the head and tail to a non-zero location in the buffer for testing
// this demonstrates proper handling of index wrap-around
ringBuffer.head = 5;
ringBuffer.tail = 5;
// fill the buffer up
while ( WriteToRingBuffer( &ringBuffer, data ) )
{
printf( "Wrote %u, buffer now has %d items\n", data, itemCountInRingBuffer( &ringBuffer ) );
data++;
}
// empty the buffer out
while ( ringBuffer.tail != ringBuffer.head )
{
data = ReadFromRingBuffer( &ringBuffer );
printf( "Read %u, there are %d items remaining\n", data, itemCountInRingBuffer( &ringBuffer ) );
}
}
请注意,如果您打算使用环形缓冲区在线程之间传递数据,或者从中断例程传递到后台代码,那么您需要使用适当的锁定机制,或者您需要成为无锁多线程的专家-threading。
答案 1 :(得分:0)
如果您要问的是如何以包装方式递增指针,答案非常简单。您需要将uint64_t类型转换替换为平台上指针的大小。如果所有低位都为零,则第二个语句包装指针。
p ++;
p -= ((uint64_t) p) & (LIGHTWEIGHT_RING_BUFFER_SIZE - 1) ?
0 : LIGHTWEIGHT_RING_BUFFER_SIZE;
或者,再次用适当的替换类型转换
p = (uint8_t *) (((uint64_t) p & ~(LIGHTWEIGHT_RING_BUFFER_SIZE - 1)) |
(((uint64_t) p + 1) & (LIGHTWEIGHT_RING_BUFFER_SIZE - 1)));