Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdint.h>
- #include <stdbool.h>
- #include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- // Rules: head == tail: Buffer is empty
- // (head+1)%len == tail: Buffer is full
- // max capacity is len-1
- typedef struct
- {
- uint8_t * data;
- size_t len;
- size_t head; // only modified by RBPut
- size_t tail; // only modified by RBGet
- } ringBuffer;
- static void RBInit (ringBuffer * r, uint8_t * data, size_t len)
- {
- r->data = data;
- r->len = len;
- r->head = 0;
- r->tail = 0;
- }
- static inline bool RBIsEmpty(const ringBuffer * r)
- {
- return (r->head == r->tail);
- }
- static inline bool RBIsFull(const ringBuffer * r)
- {
- size_t next = (r->head+1 == r->len) ? 0: r->head+1;
- return next == r->tail;
- }
- static inline void RBPut (ringBuffer * r, uint8_t item)
- {
- // caller must ensure the buffer is not full!
- r->data[r->head] = item; // write item *before* updating index!
- // prevent GCC from reordering memory before updating index
- asm volatile("": : :"memory");
- size_t next = (r->head+1 == r->len) ? 0 : r->head+1;
- r->head = next; // update index
- }
- static inline uint8_t RBGet (ringBuffer * r)
- {
- // caller must ensure the buffer is not empty!
- uint8_t result = r->data[r->tail]; // get item *before* updating index
- // prevent GCC from reordering memory before updating index
- asm volatile("": : :"memory");
- size_t next = (r->tail+1 == r->len) ? 0 : r->tail+1;
- r->tail = next; // update index
- return result;
- }
- bool chance (int q)
- {
- int n = rand()&255;
- return (n<q);
- }
- int main (int argc, char **args)
- {
- uint8_t data[10];
- ringBuffer buf;
- RBInit (&buf, data, sizeof (data));
- uint8_t expectedRead = 0;
- uint8_t nextItem = 0;
- // stress test:
- for (int i=0; i<10000000; i++)
- {
- // emulate different access-patterns
- int writeChance = i / 331;
- int readChance = i / 569;
- if (!RBIsFull (&buf))
- {
- if (chance(writeChance & 255))
- {
- // insert a byte:
- RBPut (&buf, nextItem++);
- }
- }
- if (!RBIsEmpty (&buf))
- {
- if (chance(readChance & 255))
- {
- // insert a byte:
- uint8_t x = RBGet (&buf);
- assert (x == expectedRead);
- expectedRead++;
- }
- }
- }
- printf ("test passed\n");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement