/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #ifndef __FENNIX_KERNEL_RING_BUFFER_H__ #define __FENNIX_KERNEL_RING_BUFFER_H__ #include #include /** * @brief A generic ring buffer implementation with thread safety. * * @tparam T Type of the data stored in the buffer. */ template class RingBuffer { private: spin_lock *Lock; T *Buffer; size_t BufferSize; size_t BufferCount; size_t Head; size_t Tail; public: /** * @brief Construct a new RingBuffer object. * * Initializes the buffer and the spin lock. The default buffer size is 16. * * @param Size Initial size (capacity) of the buffer. */ RingBuffer(size_t Size = 16) : Lock(new spin_lock()), Buffer(new T[Size]), BufferSize(Size), BufferCount(0), Head(0), Tail(0) {} /** * @brief Destroy the RingBuffer object. * * Releases the allocated memory for the buffer and the spin lock. */ ~RingBuffer() { delete Lock; delete[] Buffer; } /** * @brief Write data to the ring buffer. * * Writes up to `nReads` elements from `Data` into the buffer. If the buffer * is full, the function stops writing. * * @param Data Pointer to the data to be written. * @param nReads Number of elements to write. * @return size_t Number of elements actually written. */ size_t Write(const T *Data, size_t nReads) { sl_guard(*Lock); size_t written = 0; while (nReads > 0) { if (BufferCount == BufferSize) break; Buffer[Head] = *Data++; Head = (Head + 1) % BufferSize; BufferCount++; written++; nReads--; } return written; } /** * @brief Read data from the ring buffer. * * Reads up to `nReads` elements from the buffer into `Data`. If the buffer * is empty, the function stops reading. * * @param Data Pointer to the memory where read elements will be stored. * @param nReads Number of elements to read. * @return size_t Number of elements actually read. */ size_t Read(T *Data, size_t nReads) { sl_guard(*Lock); size_t read = 0; while (nReads > 0) { if (BufferCount == 0) break; *Data++ = Buffer[Tail]; Tail = (Tail + 1) % BufferSize; BufferCount--; read++; nReads--; } return read; } /** * @brief Peek at data in the ring buffer without removing it. * * Peeks up to `nReads` elements from the buffer into `Data` without * modifying the buffer state. If the buffer is empty, the function stops peeking. * * @param Data Pointer to the memory where peeked elements will be stored. * @param nReads Number of elements to peek. * @return size_t Number of elements actually peeked. */ size_t Peek(T *Data, size_t nReads) { sl_guard(*Lock); size_t read = 0; size_t tail = Tail; while (nReads > 0) { if (BufferCount == 0) break; *Data++ = Buffer[tail]; tail = (tail + 1) % BufferSize; read++; nReads--; } return read; } /** * @brief Get the current number of elements in the buffer. * * @return size_t The number of elements in the buffer. */ size_t Count() { sl_guard(*Lock); return BufferCount; } /** * @brief Get the available space left in the buffer. * * @return size_t The number of free slots in the buffer. */ size_t Free() { sl_guard(*Lock); return BufferSize - BufferCount; } }; #endif // !__FENNIX_KERNEL_RING_BUFFER_H__