Skip to content

Commit

Permalink
Merge pull request #3 from vascojdb/master
Browse files Browse the repository at this point in the history
Major updates for ESP8266. Changed constructors with configurable items count and/or bytes size
  • Loading branch information
EinarArnason authored Apr 3, 2019
2 parents 2bad49b + c61fa25 commit f6acf80
Show file tree
Hide file tree
Showing 4 changed files with 331 additions and 32 deletions.
148 changes: 119 additions & 29 deletions Queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -15,7 +18,7 @@
#endif

template <typename T>
class Queue {
class DataQueue {
class Node {
public:
T item;
Expand All @@ -29,39 +32,82 @@ 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;
}

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;
}

Expand All @@ -74,42 +120,86 @@ 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
is empty, a dummy item is
returned.
*/
T front() {
if (head == NULL) {
if ((_items_cnt == 0) || (_head == NULL)) {
return T();
}

T item = head->item;

T item = _head->item;
return item;
}
};
65 changes: 62 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,68 @@
A lightweight linked list type queue implementation, meant for microcontrollers.
Written as a C++ template class.

## Example:
`Queue<int> intQueue;`
## Constructors:
Creates a queue up to *<maximum_number_of_items>* items:
```
DataQueue<T> intQueue(maximum_number_of_items);
```
Creates a queue up to *<maximum_size_in_bytes>* bytes:
```
DataQueue<T> intQueue(0, maximum_size_in_bytes);
```
Creates a queue up to *<maximum_number_of_items>* items or *<maximum_size_in_bytes>* bytes, whatever comes first:
```
DataQueue<T> 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 <Queue.h>
```

Then create the queue according to your needs, examples:

* To create a queue of ***int***, capable of holding 20 items:
```
DataQueue<int> intQueue(20);
```

* To create a queue of ***int***, capable of holding 20 items or a maximum size of 10 bytes *(whatever comes first)*:
```
DataQueue<int> 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<car> 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()*.
73 changes: 73 additions & 0 deletions examples/intQueueItemsSize/intQueueItemsSize.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
Author: Vasco Baptista
email: [email protected]
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<int> 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<QUEUE_SIZE_ITEMS+5; n++) {
if (!intQueue.isFull()) {
Serial.printf("Adding value: %i\r\n", n);
intQueue.enqueue(n);
}
else {
Serial.println("Queue is full!");
}
}

printQueueStats();

// Remove elements: (remove more than the queue size for demo purposes)
for(int n=1; n<QUEUE_SIZE_ITEMS+5; n++) {
if (!intQueue.isEmpty()) {

int value = intQueue.dequeue();
Serial.printf("Removed value: %i\r\n", value);
}
else {
Serial.println("Queue is empty!");
}
}

printQueueStats();

// Loop forever
while(true) {
#ifdef ESP8266
ESP.wdtFeed();
#endif
}
}
Loading

0 comments on commit f6acf80

Please sign in to comment.