c - Increase a pointer's LSB bits but keep the rest (hardcoded ringbuffer size) -
i try code compact ringbuffer. buffer holds 2^x values (x: 1-7) need increase x bits (lsb) keep rest of variables. ive got solution dont know if works (never modified pointer address before) , not compact. idea how improve this?
// hardcoded ringbuffersize better ram usage // frees 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 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 lsb bits buffer->in >>= lightweight_ring_buffer_bits; buffer->in <<= lightweight_ring_buffer_bits; // save lsb bits + 1 buffer->in |= ++pointermask & (lightweight_ring_buffer_size - 1) buffer->count++;
here's simple ring buffer implementation looks like. size of ring buffer determined mask. value mask must 2n-1, n <= 8. 256 byte ring buffer, can eliminate mask altogether.
#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 ring buffer full // argument byte stored in 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 byte ring buffer, or 0 if buffer empty // caller responsible making sure buffer not empty before calling 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 number of items in ring buffer int itemcountinringbuffer( stringbuffer *buffer ) { return( (buffer->head - buffer->tail) & mask ); } int main( void ) { uint8_t data = 31; // move head , tail non-zero location in buffer testing // demonstrates proper handling of index wrap-around ringbuffer.head = 5; ringbuffer.tail = 5; // fill buffer while ( writetoringbuffer( &ringbuffer, data ) ) { printf( "wrote %u, buffer has %d items\n", data, itemcountinringbuffer( &ringbuffer ) ); data++; } // empty buffer out while ( ringbuffer.tail != ringbuffer.head ) { data = readfromringbuffer( &ringbuffer ); printf( "read %u, there %d items remaining\n", data, itemcountinringbuffer( &ringbuffer ) ); } } note if intend use ring buffer pass data between threads, or interrupt routine background code, either need use appropriate locking mechanisms, or need become expert in lockless multi-threading.
Comments
Post a Comment