diff --git a/Queue.h b/Queue.h index 33f0194..246a917 100644 --- a/Queue.h +++ b/Queue.h @@ -4,6 +4,9 @@ A lightweight linked list type queue implementation, meant for microcontrollers. + + Usage and further info: + https://github.com/EinarArnason/ArduinoQueue */ #pragma once @@ -15,7 +18,7 @@ #endif template -class Queue { +class DataQueue { class Node { public: T item; @@ -29,23 +32,65 @@ class Queue { next = NULL; } }; - Node* head; - Node* tail; + Node* _head; + Node* _tail; + unsigned int _max_items; + unsigned int _max_memory; + unsigned int _items_cnt; + public: - Queue() { - head = NULL; - tail = NULL; + DataQueue(unsigned int max_items = 100, unsigned int max_memory = 0) { + _head = NULL; + _tail = NULL; + + /* + If the max memory has not + been defined or is 0, then + the queue size is set by + the max number of items: + */ + if (max_memory == 0) { + _max_items = max_items; + _max_memory = max_items * sizeof(T); + } + /* + If the max memory has been + set then the queue size is + defined by the memory size + when the max items is 0. + If the user gave a max item + size, then the queue size + will be capped by the number + of items. + */ + else { + _max_items = max_memory / sizeof(T); + _max_memory = _max_items * sizeof(T); + if (max_items != 0) { + if (_max_items > max_items) + _max_items = max_items; + } + } + _items_cnt = 0; } - ~Queue() { - for (Node* node = head; node != NULL; node = head) { - head = node->next; + ~DataQueue() { + for (Node* node = _head; node != NULL; node = _head) { + _head = node->next; delete node; } } - // Returns false if memory is full, otherwise true + /* + Push an item to the queue. + Returns false if memory is + full, or true if the item + was added to queue. + */ bool enqueue(T item) { + if (_items_cnt == _max_items) { + return false; + } Node* node = new Node; if (node == NULL) { return false; @@ -53,15 +98,16 @@ class Queue { node->item = item; - if (head == NULL) { - head = node; - tail = node; + if (_head == NULL) { + _head = node; + _tail = node; + _items_cnt++; return true; } - tail->next = node; - tail = node; - + _tail->next = node; + _tail = node; + _items_cnt++; return true; } @@ -74,29 +120,75 @@ class Queue { returned. */ T dequeue() { - if (head == NULL) { + if ((_items_cnt == 0) || (_head == NULL)) { return T(); } - Node* node = head; - head = node->next; + Node* node = _head; + _head = node->next; T item = node->item; delete node; node = NULL; - - if (head == NULL) { - tail = NULL; + + if (_head == NULL) { + _tail = NULL; } - + + _items_cnt--; return item; } + /* + Returns true if the queue + is empty, false otherwise. + */ bool isEmpty() { - return head == NULL; + return _head == NULL; + } + + /* + Returns true if the queue + is full, false otherwise. + */ + bool isFull() { + return _items_cnt == _max_items; } /* - Get the front of the queue. + Returns the number of items + currently in the queue. + */ + unsigned int item_count() { + return _items_cnt; + } + + /* + Returns the size of the + queue item in bytes. + */ + unsigned int item_size() { + return sizeof(T); + } + + /* + Returns the size of the queue + (maximum number of items) + */ + unsigned int max_queue_size() { + return _max_items; + } + + /* + Returns the size of the queue + (maximum size in bytes) + */ + unsigned int max_memory_size() { + return _max_memory; + } + + /* + Get the item in the front + of the queue. Because exceptions are not usually implemented for microcontrollers, if queue @@ -104,12 +196,10 @@ class Queue { returned. */ T front() { - if (head == NULL) { + if ((_items_cnt == 0) || (_head == NULL)) { return T(); } - - T item = head->item; - + T item = _head->item; return item; } }; diff --git a/README.md b/README.md index c114305..ac8f538 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,68 @@ A lightweight linked list type queue implementation, meant for microcontrollers. Written as a C++ template class. -## Example: -`Queue intQueue;` +## Constructors: +Creates a queue up to ** items: +``` +DataQueue intQueue(maximum_number_of_items); +``` +Creates a queue up to ** bytes: +``` +DataQueue intQueue(0, maximum_size_in_bytes); +``` +Creates a queue up to ** items or ** bytes, whatever comes first: +``` +DataQueue intQueue(maximum_number_of_items, maximum_size_in_bytes); +``` -all the T's will then be replaced by int. +## How to use: +Include the header file on your code: +``` +#include +``` +Then create the queue according to your needs, examples: + +* To create a queue of ***int***, capable of holding 20 items: +``` +DataQueue intQueue(20); +``` + +* To create a queue of ***int***, capable of holding 20 items or a maximum size of 10 bytes *(whatever comes first)*: +``` +DataQueue intQueue(20, 10); +``` + +* To create a queue of your ***defined structure***, capable of holding 50 items: +``` +struct car { + char brand[10]; + char model[10]; + int nr_doors; +}; +DataQueue myCarsQueue(50); +``` + +Finally use the following functions: +``` +intQueue.enqueue(1); // Adds number 1 to the queue +intQueue.enqueue(123); // Adds number 123 to the queue +int number = intQueue.dequeue(); // Will return number 1 and remove it from the queue +int number = intQueue.front(); // Will return number 123 but leave it still in the queue +int number = intQueue.dequeue(); // Will return number 123 and remove it from the queue +``` + +You can use also the following functions to get more queue properties: +``` +bool state = intQueue.isEmpty(); // Returns true if the queue is empty, false otherwise +bool state = intQueue.isFull(); // Returns true if the queue is full, false otherwise +unsigned int n = intQueue.item_count(); // Returns the number of items currently on the queue +unsigned int n = intQueue.item_size(); // Returns the size of the item being stored (bytes) +unsigned int n = intQueue.max_queue_size(); // Returns the maximum possible size of the queue (items)* +unsigned int n = intQueue.max_memory_size(); // Returns the maximum possible size of the queue (bytes)* +``` + +## Notes Note that while the Queue class cleans up the nodes in memory after destructor or dequeue is called, it keeps a copy of the item being queued. So for example if you are queuing pointers, you will need to keep track of the memory behind them. + +*For example if you create a queue of *int* on an ESP8266, where each *int* has a size of 4 bytes and you specify the queue sizes to be up to 10 items and 10 bytes on the constructor, actually the real values will be 2 items and 8 bytes. These will be the values returned by *max_queue_size()* and *max_memory_size()*. \ No newline at end of file diff --git a/examples/intQueueItemsSize/intQueueItemsSize.ino b/examples/intQueueItemsSize/intQueueItemsSize.ino new file mode 100644 index 0000000..934df57 --- /dev/null +++ b/examples/intQueueItemsSize/intQueueItemsSize.ino @@ -0,0 +1,73 @@ +/* + Author: Vasco Baptista + email: vascojdb@gmail.com + + An example of using Einar Arnason's queue + In this example we create a queue of int's + limited by the maximum amount of items + + Usage and further info: + https://github.com/EinarArnason/ArduinoQueue +*/ + +#include "Queue.h" + +#define QUEUE_SIZE_ITEMS 10 + +// Queue creation: +DataQueue intQueue(QUEUE_SIZE_ITEMS); + +void printQueueStats() { + Serial.println(""); + Serial.printf("Size of each element: %u bytes\r\n", intQueue.item_size()); + Serial.printf("Items in queue now: %u items\r\n", intQueue.item_count()); + Serial.printf("Queue actual max items: %u items\r\n", intQueue.max_queue_size()); + Serial.printf("Queue actual max memory: %u bytes\r\n", intQueue.max_memory_size()); + Serial.println(""); +} + +void setup() { + Serial.begin(115200); + Serial.println(""); + Serial.println("========== Queue example =========="); + Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); + Serial.println("==================================="); +} + +void loop() { + printQueueStats(); + + // Add elements: (add more than the queue size for demo purposes) + for(int n=1; n intQueue(QUEUE_SIZE_ITEMS, QUEUE_SIZE_BYTES); + +void printQueueStats() { + Serial.println(""); + Serial.printf("Size of each element: %u bytes\r\n", intQueue.item_size()); + Serial.printf("Items in queue now: %u items\r\n", intQueue.item_count()); + Serial.printf("Queue actual max items: %u items\r\n", intQueue.max_queue_size()); + Serial.printf("Queue actual max memory: %u bytes\r\n", intQueue.max_memory_size()); + Serial.println(""); +} + +void setup() { + Serial.begin(115200); + Serial.println(""); + Serial.println("========== Queue example =========="); + Serial.printf("Desired max item size: %u items\r\n", QUEUE_SIZE_ITEMS); + Serial.printf("Desired max queue size: %u bytes\r\n", QUEUE_SIZE_BYTES); + Serial.println("==================================="); +} + +void loop() { + printQueueStats(); + + // Add elements: (add more than the queue size for demo purposes) + for(int n=1; n