move pool/queue management into the rf95 lib

This commit is contained in:
geeksville
2020-04-14 13:20:36 -07:00
parent 5904d66111
commit 80c69c28cd
3 changed files with 0 additions and 0 deletions

80
src/rf95/MemoryPool.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
#include <Arduino.h>
#include <assert.h>
#include "PointerQueue.h"
/**
* A pool based allocator
*
* Eventually this routine will even be safe for ISR use...
*/
template <class T> class MemoryPool
{
PointerQueue<T> dead;
T *buf; // our large raw block of memory
size_t maxElements;
public:
MemoryPool(size_t _maxElements) : dead(_maxElements), maxElements(_maxElements)
{
buf = new T[maxElements];
// prefill dead
for (int i = 0; i < maxElements; i++)
release(&buf[i]);
}
~MemoryPool() { delete[] buf; }
/// Return a queable object which has been prefilled with zeros. Panic if no buffer is available
T *allocZeroed()
{
T *p = allocZeroed(0);
assert(p); // FIXME panic instead
return p;
}
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you probably
/// don't want this version)
T *allocZeroed(TickType_t maxWait)
{
T *p = dead.dequeuePtr(maxWait);
if (p)
memset(p, 0, sizeof(T));
return p;
}
/// Return a queable object which is a copy of some other object
T *allocCopy(const T &src, TickType_t maxWait = portMAX_DELAY)
{
T *p = dead.dequeuePtr(maxWait);
if (p)
*p = src;
return p;
}
/// Return a buffer for use by others
void release(T *p)
{
assert(dead.enqueue(p, 0));
assert(p >= buf &&
(p - buf) <
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
}
/// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-)
void releaseFromISR(T *p, BaseType_t *higherPriWoken)
{
assert(dead.enqueueFromISR(p, higherPriWoken));
assert(p >= buf &&
(p - buf) <
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
}
};

28
src/rf95/PointerQueue.h Normal file
View File

@@ -0,0 +1,28 @@
#pragma once
#include "TypedQueue.h"
/**
* A wrapper for freertos queues that assumes each element is a pointer
*/
template <class T> class PointerQueue : public TypedQueue<T *>
{
public:
PointerQueue(int maxElements) : TypedQueue<T *>(maxElements) {}
// returns a ptr or null if the queue was empty
T *dequeuePtr(TickType_t maxWait = portMAX_DELAY)
{
T *p;
return this->dequeue(&p, maxWait) ? p : nullptr;
}
// returns a ptr or null if the queue was empty
T *dequeuePtrFromISR(BaseType_t *higherPriWoken)
{
T *p;
return this->dequeueFromISR(&p, higherPriWoken) ? p : nullptr;
}
};

38
src/rf95/TypedQueue.h Normal file
View File

@@ -0,0 +1,38 @@
#pragma once
#include <cassert>
#include <type_traits>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
/**
* A wrapper for freertos queues. Note: each element object should be small
* and POD (Plain Old Data type) as elements are memcpied by value.
*/
template <class T> class TypedQueue
{
static_assert(std::is_pod<T>::value, "T must be pod");
QueueHandle_t h;
public:
TypedQueue(int maxElements)
{
h = xQueueCreate(maxElements, sizeof(T));
assert(h);
}
~TypedQueue() { vQueueDelete(h); }
int numFree() { return uxQueueSpacesAvailable(h); }
bool isEmpty() { return uxQueueMessagesWaiting(h) == 0; }
bool enqueue(T x, TickType_t maxWait = portMAX_DELAY) { return xQueueSendToBack(h, &x, maxWait) == pdTRUE; }
bool enqueueFromISR(T x, BaseType_t *higherPriWoken) { return xQueueSendToBackFromISR(h, &x, higherPriWoken) == pdTRUE; }
bool dequeue(T *p, TickType_t maxWait = portMAX_DELAY) { return xQueueReceive(h, p, maxWait) == pdTRUE; }
bool dequeueFromISR(T *p, BaseType_t *higherPriWoken) { return xQueueReceiveFromISR(h, p, higherPriWoken); }
};