Advertisement
Guest User

Untitled

a guest
Oct 27th, 2018
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.60 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdbool.h>
  3. #include <stddef.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7.  
  8. // Rules: head == tail: Buffer is empty
  9. //        (head+1)%len == tail: Buffer is full
  10. //        max capacity is len-1
  11.  
  12. typedef struct
  13. {
  14.     uint8_t *   data;
  15.     size_t      len;
  16.     size_t      head;       // only modified by RBPut
  17.     size_t      tail;       // only modified by RBGet
  18. } ringBuffer;
  19.  
  20.  
  21. static void RBInit (ringBuffer * r, uint8_t * data, size_t len)
  22. {
  23.     r->data = data;
  24.     r->len  = len;
  25.     r->head = 0;
  26.     r->tail = 0;
  27. }
  28.  
  29. static inline bool RBIsEmpty(const ringBuffer * r)
  30. {
  31.     return (r->head == r->tail);
  32. }
  33.  
  34. static inline bool RBIsFull(const ringBuffer * r)
  35. {
  36.     size_t next = (r->head+1 == r->len) ? 0: r->head+1;
  37.     return next == r->tail;
  38. }
  39.  
  40. static inline void RBPut (ringBuffer * r, uint8_t item)
  41. {
  42.     // caller must ensure the buffer is not full!
  43.     r->data[r->head] = item;           // write item *before* updating index!
  44.     // prevent GCC from reordering memory before updating index
  45.     asm volatile("": : :"memory");  
  46.     size_t next = (r->head+1 == r->len) ? 0 : r->head+1;
  47.     r->head = next;                 // update index
  48. }
  49.  
  50. static inline uint8_t RBGet (ringBuffer * r)
  51. {
  52.     // caller must ensure the buffer is not empty!
  53.     uint8_t result = r->data[r->tail]; // get item *before* updating index
  54.     // prevent GCC from reordering memory before updating index
  55.     asm volatile("": : :"memory");  
  56.     size_t next = (r->tail+1 == r->len) ? 0 : r->tail+1;
  57.     r->tail = next;                 // update index
  58.     return result;
  59. }
  60.  
  61.  
  62.  
  63. bool chance (int q)
  64. {
  65.     int n = rand()&255;
  66.     return (n<q);
  67. }
  68.  
  69.  
  70. int main (int argc, char **args)
  71. {
  72.     uint8_t data[10];
  73.     ringBuffer buf;
  74.  
  75.    
  76.     RBInit (&buf, data, sizeof (data));
  77.  
  78.     uint8_t expectedRead = 0;
  79.     uint8_t nextItem = 0;
  80.  
  81.     // stress test:
  82.     for (int i=0; i<10000000; i++)
  83.     {
  84.         // emulate different access-patterns
  85.         int writeChance = i / 331;
  86.         int readChance  = i / 569;
  87.        
  88.         if (!RBIsFull (&buf))
  89.         {
  90.             if (chance(writeChance & 255))
  91.             {
  92.                 // insert a byte:
  93.                 RBPut (&buf, nextItem++);
  94.             }
  95.         }
  96.         if (!RBIsEmpty (&buf))
  97.         {
  98.             if (chance(readChance & 255))
  99.             {
  100.                 // insert a byte:
  101.                 uint8_t x = RBGet (&buf);
  102.                 assert (x == expectedRead);
  103.                 expectedRead++;
  104.             }
  105.         }
  106.     }
  107.     printf ("test passed\n");
  108.     return 0;
  109. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement