| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- //============================================================================
- // Lock-Free Ring Buffer (LFRB) for embedded systems
- // GitHub: https://github.com/QuantumLeaps/lock-free-ring-buffer
- //
- // Q u a n t u m L e a P s
- // ------------------------
- // Modern Embedded Software
- //
- // Copyright (C) 2005 Quantum Leaps, <state-machine.com>.
- //
- // SPDX-License-Identifier: MIT
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the "Software"),
- // to deal in the Software without restriction, including without limitation
- // the rights to use, copy, modify, merge, publish, distribute, sublicense,
- // and/or sell copies of the Software, and to permit persons to whom the
- // Software is furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- // DEALINGS IN THE SOFTWARE.
- //============================================================================
- #ifndef RING_BUF_H
- #define RING_BUF_H
- #include <stdatomic.h>
- #include <stdint.h>
- #include <stdbool.h>
- //! Ring buffer counter/index
- //
- // @attention
- // The following RingBufCtr type is assumed to be "atomic" in a target CPU,
- // meaning that the CPU needs to write the whole RingBufCtr in one machine
- // instruction. An example of violating this assumption would be an 8-bit
- // CPU, which writes uint16_t (2-bytes) in 2 machine instructions. For such
- // 8-bit CPU, the maximum size of RingBufCtr would be uint8_t (1-byte).
- //
- // Another case of violating the "atomic" writes to RingBufCtr type would
- // be misalignment of a RingBufCtr variable in memory, which could cause
- // the compiler to generate multiple instructions to write a RingBufCtr value.
- // Therefore, it is further assumed that all RingBufCtr variables in the
- // following RingBuf struct *are* correctly aligned for "atomic" access.
- //In practice, most C compilers should provide such natural alignment
- // (by inserting some padding into the ::RingBuf struct, if necessary).
- //
- typedef uint16_t RingBufCtr;
- //! Ring buffer element type
- //
- // @details
- // The type of the ring buffer elements is not critical for the lock-free
- // operation and does not need to be "atomic". For example, it can be
- // an integer type (uint16_t, uint32_t, uint64_t), a pointer type,
- // or even a struct type. However, the bigger the type the more RAM is
- // needed for the ring buffer and more CPU cycles are needed to copy it
- // into and out of the buffer memory.
- //
- typedef uint8_t RingBufElement;
- //! Ring buffer struct
- typedef struct {
- RingBufElement *buf; //!< pointer to the start of the ring buffer
- RingBufCtr end; //!< index of the end of the ring buffer
- //! atomic index to where next element will be inserted
- _Atomic(RingBufCtr) head;
- //! atomic index to where next element will be removed
- _Atomic(RingBufCtr) tail;
- } RingBuf;
- void RingBuf_ctor(RingBuf * const me,
- RingBufElement sto[], RingBufCtr sto_len);
- RingBufCtr RingBuf_num_free(RingBuf * const me);
- bool RingBuf_put(RingBuf * const me, RingBufElement const el);
- bool RingBuf_get(RingBuf * const me, RingBufElement *pel);
- //! Ring buffer callback function for RingBuf_process_all()
- //
- // @details
- // The callback processes one element and runs in the context of
- // RingBuf_process_all().
- //
- typedef void (*RingBufHandler)(RingBufElement const el);
- void RingBuf_process_all(RingBuf * const me, RingBufHandler handler);
- #endif // RING_BUF_H
|