Ring buffer in C.txt 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. http://tath.eu/code/ring-buffer-in-c/
  2. Ring buffer is very common and useful data structure, excellent for storing
  3. asynchronous data from multiple sources in embedded devices.
  4. ringbuffer.h
  5. // Simple prove-of-concept ring buffer
  6. // Author: Adam Orcholski, www.tath.eu
  7. #pragma once
  8. // types
  9. typedef struct ring_buffer_s
  10. {
  11. unsigned char * data; // pointer to external buffer
  12. int size; // size of external buffer
  13. int head; // index of free space in external buffer
  14. int tail; // index of last item to be read
  15. int count; // hold number of items stored but not read
  16. } ring_buffer_t;
  17. // interface
  18. void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes);
  19. void RING_Reset(ring_buffer_t * const buff_state); // note: does not clear external buffer
  20. int RING_IsEmpty(ring_buffer_t * const buff_state); // return non-zero if buffer is empty
  21. int RING_IsFull(ring_buffer_t * const buff_state); // return non-zero if buffer is full
  22. int RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item); // return non-zero if buffer is full
  23. int RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item); // return non-zero if buffer is empty
  24. ringbuffer.c
  25. // Simple prove-of-concept ring buffer
  26. // Author: Adam Orcholski, www.tath.eu
  27. #include <ringbuffer.h>
  28. #include <assert.h>
  29. // function definitions
  30. void RING_Init(ring_buffer_t * const buff_state, unsigned char * in_buffer, int buffer_size_in_bytes)
  31. {
  32. assert(0 != buff_state);
  33. assert(0 != in_buffer);
  34. assert(buffer_size_in_bytes > 0);
  35. buff_state->data = in_buffer;
  36. buff_state->size = buffer_size_in_bytes;
  37. buff_state->head = 0;
  38. buff_state->tail = 0;
  39. buff_state->count = 0;
  40. }
  41. void RING_Reset(ring_buffer_t * const buff_state)
  42. {
  43. assert(0 != buff_state);
  44. buff_state->head = 0;
  45. buff_state->tail = 0;
  46. buff_state->count = 0;
  47. }
  48. // return non-zero value if buffer is empty
  49. int RING_IsEmpty(ring_buffer_t * const buff_state)
  50. {
  51. int fBufferIsEmpty = 0;
  52. assert(0 != buff_state);
  53. if (0 == buff_state->count)
  54. {
  55. fBufferIsEmpty = 1;
  56. }
  57. return fBufferIsEmpty;
  58. }
  59. // return non-zero value if buffer is full
  60. int RING_IsFull(ring_buffer_t * const buff_state)
  61. {
  62. int fBufferIsFull = 0;
  63. assert(0 != buff_state);
  64. if (buff_state->count >= buff_state->size)
  65. {
  66. fBufferIsFull = 1;
  67. }
  68. return fBufferIsFull;
  69. }
  70. // return non-zero value if buffer is full
  71. int RING_AddItem(ring_buffer_t * const buff_state, unsigned char new_item)
  72. {
  73. int fBufferIsFull = 0;
  74. assert(0 != buff_state);
  75. fBufferIsFull = RING_IsFull(buff_state);
  76. if (!fBufferIsFull)
  77. {
  78. buff_state->data[buff_state->head] = new_item;
  79. buff_state->head++;
  80. buff_state->count++;
  81. if (buff_state->head >= buff_state->size)
  82. {
  83. buff_state->head = 0;
  84. }
  85. }
  86. return fBufferIsFull;
  87. }
  88. // return non-zero value if buffer is empty
  89. int RING_GetItem(ring_buffer_t * const buff_state, unsigned char * const out_item)
  90. {
  91. int fBufferIsEmpty = 0;
  92. assert(0 != buff_state);
  93. assert(0 != out_item);
  94. fBufferIsEmpty = RING_IsEmpty(buff_state);
  95. if (!fBufferIsEmpty)
  96. {
  97. *out_item = buff_state->data[buff_state->tail];
  98. buff_state->tail++;
  99. buff_state->count--;
  100. if (buff_state->tail >= buff_state->size)
  101. {
  102. buff_state->tail = 0;
  103. }
  104. }
  105. return fBufferIsEmpty;
  106. }
  107. and example/test compiled in Microsoft Visual Studio:
  108. main.c
  109. // Simple prove-of-concept ring buffer example
  110. // Author: Adam Orcholski, www.tath.eu
  111. #include <stdio.h>
  112. #include <ringbuffer.h>
  113. #define BUFF_SIZE 4
  114. unsigned char bufffeeer[BUFF_SIZE];
  115. ring_buffer_t buff;
  116. int main()
  117. {
  118. RING_Init(&buff, bufffeeer, sizeof(bufffeeer));
  119. char c = 0;
  120. while (c != 'q')
  121. {
  122. static char write_char = 'a';
  123. c = getchar();
  124. int ret = 0;
  125. if (c == 'w')
  126. {
  127. ret = RING_AddItem(&buff, write_char);
  128. if (ret)
  129. {
  130. printf("buffer full\r\n");
  131. }
  132. else
  133. {
  134. printf("written char = %c\r\n", write_char);
  135. }
  136. write_char++;
  137. if (write_char == 'z') { write_char = 'a'; }
  138. }
  139. else if (c == 's')
  140. {
  141. char out;
  142. ret = RING_GetItem(&buff, &out);
  143. if (ret)
  144. {
  145. printf("buffer empty\r\n");
  146. }
  147. else
  148. {
  149. printf("read char = %c\r\n", out);
  150. }
  151. }
  152. }
  153. return 0;
  154. }
  155. Run example, and press W key to add item to buffer and S key to read last item. Press Q to quit.