From 7e7c4e56ede3510bd58770acc46a95a757acd269 Mon Sep 17 00:00:00 2001 From: Vasco Baptista Date: Sun, 10 Mar 2019 17:50:10 +0100 Subject: [PATCH 1/2] Updated class name. Added function isFull() and count(). Updated readme file Changed name Queue to DataQueue because of ESP8266 already including a conflicting name. This will solve the compilation errors. Added a maximum limit for number of messages in queue, defaults to 100, added function isFull() and count(). Completed the README file with more info. --- Queue.h | 49 +++++++++++++++++++++++++++++++++++++++++-------- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/Queue.h b/Queue.h index 33f0194..0c5df33 100644 --- a/Queue.h +++ b/Queue.h @@ -9,13 +9,13 @@ #pragma once #if defined(ARDUINO) && ARDUINO >= 100 -#include "Arduino.h" +#include "arduino.h" #else #include "WProgram.h" #endif template -class Queue { +class DataQueue { class Node { public: T item; @@ -31,13 +31,19 @@ class Queue { }; Node* head; Node* tail; + uint8_t max_items; + uint8_t items; public: - Queue() { + DataQueue(int m_size = 100) { head = NULL; tail = NULL; + if (m_size > 255) m_size = 255; + if (m_size < 0) m_size = 0; + max_items = m_size; + items = 0; } - ~Queue() { + ~DataQueue() { for (Node* node = head; node != NULL; node = head) { head = node->next; delete node; @@ -46,6 +52,10 @@ class Queue { // Returns false if memory is full, otherwise true bool enqueue(T item) { + if (items == max_items) { + return false; + } + Node* node = new Node; if (node == NULL) { return false; @@ -56,12 +66,14 @@ class Queue { if (head == NULL) { head = node; tail = node; + items++; return true; } tail->next = node; tail = node; - + items++; + return true; } @@ -74,7 +86,7 @@ class Queue { returned. */ T dequeue() { - if (head == NULL) { + if ((items == 0) || (head == NULL)) { return T(); } @@ -88,12 +100,33 @@ class Queue { tail = NULL; } + items--; return item; } + /* + Returns true if the queue + is empty, false otherwise. + */ bool isEmpty() { return head == NULL; } + + /* + Returns true if the queue + is full, false otherwise. + */ + bool isFull() { + return items == max_items; + } + + /* + Returns the number of items + in the queue. + */ + uint8_t count() { + return items; + } /* Get the front of the queue. @@ -104,7 +137,7 @@ class Queue { returned. */ T front() { - if (head == NULL) { + if ((items == 0) || (head == NULL)) { return T(); } @@ -112,4 +145,4 @@ class Queue { return item; } -}; +}; \ No newline at end of file diff --git a/README.md b/README.md index c114305..00a268d 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,51 @@ A lightweight linked list type queue implementation, meant for microcontrollers. Written as a C++ template class. -## Example: -`Queue intQueue;` +## Constructor: +``` +DataQueue intQueue(maximum_number_of_items); +``` -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 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 for getting 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 +uint8_t number = intQueue.count() // Returns the number of items on the queue +``` + +## 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. + +Note that this library was made in order to be lightweight and the maximum number of items is stored in an 8 bit unsigned number, so the **maximum number of items is 255**. If you wish to have a bigger queue *(be careful with the memory requirements!)* you may change the internal item counters from `uint8_t` *(up to 255 items)* to `uint16_t` *(up to 65.534 items)* or `uint32_t` *(up to 4.294.967.294 items)* \ No newline at end of file From c61fa25a2a4e287848e237cb15e6f941637954a3 Mon Sep 17 00:00:00 2001 From: Vasco Baptista Date: Wed, 20 Mar 2019 13:26:58 +0100 Subject: [PATCH 2/2] Constructor with queue size in items/bytes -Corrected case sensitive issue with Arduino.h -We can now create a queue based on max items or max size in bytes -Corrected tabs/spaces missaligment -Added functions: item_count, item_size, max_queue_size, max_memory_size -Updated readme --- Queue.h | 165 ++++++++++++------ README.md | 33 +++- .../intQueueItemsSize/intQueueItemsSize.ino | 73 ++++++++ examples/intQueueMemSize/intQueueMemSize.ino | 77 ++++++++ 4 files changed, 286 insertions(+), 62 deletions(-) create mode 100644 examples/intQueueItemsSize/intQueueItemsSize.ino create mode 100644 examples/intQueueMemSize/intQueueMemSize.ino diff --git a/Queue.h b/Queue.h index 0c5df33..246a917 100644 --- a/Queue.h +++ b/Queue.h @@ -4,12 +4,15 @@ A lightweight linked list type queue implementation, meant for microcontrollers. + + Usage and further info: + https://github.com/EinarArnason/ArduinoQueue */ #pragma once #if defined(ARDUINO) && ARDUINO >= 100 -#include "arduino.h" +#include "Arduino.h" #else #include "WProgram.h" #endif @@ -29,33 +32,65 @@ class DataQueue { next = NULL; } }; - Node* head; - Node* tail; - uint8_t max_items; - uint8_t items; + Node* _head; + Node* _tail; + unsigned int _max_items; + unsigned int _max_memory; + unsigned int _items_cnt; + public: - DataQueue(int m_size = 100) { - head = NULL; - tail = NULL; - if (m_size > 255) m_size = 255; - if (m_size < 0) m_size = 0; - max_items = m_size; - items = 0; + 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; } ~DataQueue() { - for (Node* node = head; node != NULL; node = head) { - head = node->next; + 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 == max_items) { - return false; - } - + if (_items_cnt == _max_items) { + return false; + } Node* node = new Node; if (node == NULL) { return false; @@ -63,17 +98,16 @@ class DataQueue { node->item = item; - if (head == NULL) { - head = node; - tail = node; - items++; + if (_head == NULL) { + _head = node; + _tail = node; + _items_cnt++; return true; } - tail->next = node; - tail = node; - items++; - + _tail->next = node; + _tail = node; + _items_cnt++; return true; } @@ -86,50 +120,75 @@ class DataQueue { returned. */ T dequeue() { - if ((items == 0) || (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--; + + _items_cnt--; return item; } - /* + /* Returns true if the queue - is empty, false otherwise. + is empty, false otherwise. */ bool isEmpty() { - return head == NULL; + return _head == NULL; } - - /* + + /* Returns true if the queue - is full, false otherwise. + is full, false otherwise. */ - bool isFull() { - return items == max_items; + bool isFull() { + return _items_cnt == _max_items; } - /* + /* Returns the number of items - in the queue. + currently in the queue. */ - uint8_t count() { - return items; - } + 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 front of the queue. + Get the item in the front + of the queue. Because exceptions are not usually implemented for microcontrollers, if queue @@ -137,12 +196,10 @@ class DataQueue { returned. */ T front() { - if ((items == 0) || (head == NULL)) { + if ((_items_cnt == 0) || (_head == NULL)) { return T(); } - - T item = head->item; - + T item = _head->item; return item; } -}; \ No newline at end of file +}; diff --git a/README.md b/README.md index 00a268d..ac8f538 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,19 @@ A lightweight linked list type queue implementation, meant for microcontrollers. Written as a C++ template class. -## Constructor: +## 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); +``` ## How to use: Include the header file on your code: @@ -15,11 +24,16 @@ Include the header file on your code: Then create the queue according to your needs, examples: -* To create a queue of **int**, capable of holding 20 items: +* 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 { @@ -34,19 +48,22 @@ 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 +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 for getting queue properties: +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 -uint8_t number = intQueue.count() // Returns the number of items on the queue +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. -Note that this library was made in order to be lightweight and the maximum number of items is stored in an 8 bit unsigned number, so the **maximum number of items is 255**. If you wish to have a bigger queue *(be careful with the memory requirements!)* you may change the internal item counters from `uint8_t` *(up to 255 items)* to `uint16_t` *(up to 65.534 items)* or `uint32_t` *(up to 4.294.967.294 items)* \ No newline at end of file +*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