ring_buf.h 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //============================================================================
  2. // Lock-Free Ring Buffer (LFRB) for embedded systems
  3. // GitHub: https://github.com/QuantumLeaps/lock-free-ring-buffer
  4. //
  5. // Q u a n t u m L e a P s
  6. // ------------------------
  7. // Modern Embedded Software
  8. //
  9. // Copyright (C) 2005 Quantum Leaps, <state-machine.com>.
  10. //
  11. // SPDX-License-Identifier: MIT
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining a
  14. // copy of this software and associated documentation files (the "Software"),
  15. // to deal in the Software without restriction, including without limitation
  16. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  17. // and/or sell copies of the Software, and to permit persons to whom the
  18. // Software is furnished to do so, subject to the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be included in
  21. // all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  26. // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  28. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  29. // DEALINGS IN THE SOFTWARE.
  30. //============================================================================
  31. #ifndef RING_BUF_H
  32. #define RING_BUF_H
  33. #include <stdatomic.h>
  34. #include <stdint.h>
  35. #include <stdbool.h>
  36. //! Ring buffer counter/index
  37. //
  38. // @attention
  39. // The following RingBufCtr type is assumed to be "atomic" in a target CPU,
  40. // meaning that the CPU needs to write the whole RingBufCtr in one machine
  41. // instruction. An example of violating this assumption would be an 8-bit
  42. // CPU, which writes uint16_t (2-bytes) in 2 machine instructions. For such
  43. // 8-bit CPU, the maximum size of RingBufCtr would be uint8_t (1-byte).
  44. //
  45. // Another case of violating the "atomic" writes to RingBufCtr type would
  46. // be misalignment of a RingBufCtr variable in memory, which could cause
  47. // the compiler to generate multiple instructions to write a RingBufCtr value.
  48. // Therefore, it is further assumed that all RingBufCtr variables in the
  49. // following RingBuf struct *are* correctly aligned for "atomic" access.
  50. //In practice, most C compilers should provide such natural alignment
  51. // (by inserting some padding into the ::RingBuf struct, if necessary).
  52. //
  53. typedef uint16_t RingBufCtr;
  54. //! Ring buffer element type
  55. //
  56. // @details
  57. // The type of the ring buffer elements is not critical for the lock-free
  58. // operation and does not need to be "atomic". For example, it can be
  59. // an integer type (uint16_t, uint32_t, uint64_t), a pointer type,
  60. // or even a struct type. However, the bigger the type the more RAM is
  61. // needed for the ring buffer and more CPU cycles are needed to copy it
  62. // into and out of the buffer memory.
  63. //
  64. typedef uint8_t RingBufElement;
  65. //! Ring buffer struct
  66. typedef struct {
  67. RingBufElement *buf; //!< pointer to the start of the ring buffer
  68. RingBufCtr end; //!< index of the end of the ring buffer
  69. //! atomic index to where next element will be inserted
  70. _Atomic(RingBufCtr) head;
  71. //! atomic index to where next element will be removed
  72. _Atomic(RingBufCtr) tail;
  73. } RingBuf;
  74. void RingBuf_ctor(RingBuf * const me,
  75. RingBufElement sto[], RingBufCtr sto_len);
  76. RingBufCtr RingBuf_num_free(RingBuf * const me);
  77. bool RingBuf_put(RingBuf * const me, RingBufElement const el);
  78. bool RingBuf_get(RingBuf * const me, RingBufElement *pel);
  79. //! Ring buffer callback function for RingBuf_process_all()
  80. //
  81. // @details
  82. // The callback processes one element and runs in the context of
  83. // RingBuf_process_all().
  84. //
  85. typedef void (*RingBufHandler)(RingBufElement const el);
  86. void RingBuf_process_all(RingBuf * const me, RingBufHandler handler);
  87. #endif // RING_BUF_H