/** * Marlin 3D Printer Firmware * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm * * This program 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. * * This program 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 this program. If not, see . * */ #ifndef __CIRCULARQUEUE_H__ #define __CIRCULARQUEUE_H__ #include /** * @brief Circular Queue class * @details Implementation of the classic ring buffer data structure */ template class CircularQueue { private: /** * @brief Buffer structure * @details This structure consolidates all the overhead required to handle * a circular queue such as the pointers and the buffer vector. */ struct buffer_t { uint8_t head; uint8_t tail; uint8_t count; uint8_t size; T queue[N]; } buffer; public: /** * @brief Class constructor * @details This class requires two template parameters, T defines the type * of item this queue will handle and N defines the maximum number of * items that can be stored on the queue. */ CircularQueue() { this->buffer.size = N; this->buffer.count = this->buffer.head = this->buffer.tail = 0; } /** * @brief Removes and returns a item from the queue * @details Removes the oldest item on the queue, pointed to by the * buffer_t head field. The item is returned to the caller. * @return type T item */ T dequeue() { if (this->isEmpty()) return T(); uint8_t index = this->buffer.head; --this->buffer.count; if (++this->buffer.head == this->buffer.size) this->buffer.head = 0; return this->buffer.queue[index]; } /** * @brief Adds an item to the queue * @details Adds an item to the queue on the location pointed by the buffer_t * tail variable. Returns false if no queue space is available. * @param item Item to be added to the queue * @return true if the operation was successful */ bool enqueue(T const &item) { if (this->isFull()) return false; this->buffer.queue[this->buffer.tail] = item; ++this->buffer.count; if (++this->buffer.tail == this->buffer.size) this->buffer.tail = 0; return true; } /** * @brief Checks if the queue has no items * @details Returns true if there are no items on the queue, false otherwise. * @return true if queue is empty */ bool isEmpty() { return this->buffer.count == 0; } /** * @brief Checks if the queue is full * @details Returns true if the queue is full, false otherwise. * @return true if queue is full */ bool isFull() { return this->buffer.count == this->buffer.size; } /** * @brief Gets the queue size * @details Returns the maximum number of items a queue can have. * @return the queue size */ uint8_t size() { return this->buffer.size; } /** * @brief Gets the next item from the queue without removing it * @details Returns the next item in the queue without removing it * or updating the pointers. * @return first item in the queue */ T peek() { return this->buffer.queue[this->buffer.head]; } /** * @brief Gets the number of items on the queue * @details Returns the current number of items stored on the queue. * @return number of items in the queue */ uint8_t count() { return this->buffer.count; } }; #endif