Skip to content

Commit

Permalink
Provide a way to override frame memory allocation
Browse files Browse the repository at this point in the history
It can be done local to a `NDArrayPool` by overriding `frameMalloc` and
`frameFree`.
It can also be also done globally by using the static method
`setDefaultFrameMemoryFunctions`
  • Loading branch information
EmilioPeJu committed Nov 21, 2023
1 parent d1772ed commit 5a4eaaf
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
9 changes: 7 additions & 2 deletions ADApp/ADSrc/NDArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ NDArray::NDArray(int nDims, size_t *dims, NDDataType_t dataType, size_t dataSize
if (pData) {
this->pData = pData;
} else {
this->pData = malloc(dataSize);
this->pData = defaultFrameMalloc(dataSize);
this->dataSize = dataSize;
}
}
Expand All @@ -73,7 +73,12 @@ NDArray::NDArray(int nDims, size_t *dims, NDDataType_t dataType, size_t dataSize
* Frees the data array, deletes all attributes, frees the attribute list and destroys the mutex. */
NDArray::~NDArray()
{
if (this->pData) free(this->pData);
if (this->pData) {
if (this->pNDArrayPool)
this->pNDArrayPool->frameFree(this->pData);
else
defaultFrameFree(this->pData);
}
delete this->pAttributeList;
}

Expand Down
9 changes: 9 additions & 0 deletions ADApp/ADSrc/NDArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
/** The maximum number of dimensions in an NDArray */
#define ND_ARRAY_MAX_DIMS 10

typedef void *(*MallocFunc_t)(size_t size);
typedef void (*FreeFunc_t)(void *ptr);
extern MallocFunc_t defaultFrameMalloc;
extern FreeFunc_t defaultFrameFree;

/** Enumeration of color modes for NDArray attribute "colorMode" */
typedef enum
{
Expand Down Expand Up @@ -182,6 +187,10 @@ class ADCORE_API NDArrayPool {
size_t getMemorySize();
int getNumFree();
void emptyFreeList();
static void setDefaultFrameMemoryFunctions(MallocFunc_t newMalloc,
FreeFunc_t newFree);
virtual void* frameMalloc(size_t size);
virtual void frameFree(void *ptr);

protected:
/** The following methods should be implemented by a pool class
Expand Down
43 changes: 41 additions & 2 deletions ADApp/ADSrc/NDArrayPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

static const char *driverName = "NDArrayPool";

// This provides a way of overriding the default memory functions for frame
// buffer allocation and freeing
MallocFunc_t defaultFrameMalloc = malloc;
FreeFunc_t defaultFrameFree = free;

/** eraseNDAttributes is a global flag the controls whether NDArray::clearAttributes() is called
* each time a new array is allocated with NDArrayPool->alloc().
Expand All @@ -53,6 +57,41 @@ NDArrayPool::NDArrayPool(class asynNDArrayDriver *pDriver, size_t maxMemory)
listLock_ = epicsMutexCreate();
}

/** Set default frame buffer allocation and deallocation functions
* \param[in] newMalloc Pointer to a function that will be used by default to
* allocate a frame buffer
* \param[in] newFree Pointer to a function that will be used by default to
* deallocate a frame buffer
* **/
void NDArrayPool::setDefaultFrameMemoryFunctions(
MallocFunc_t newMalloc, FreeFunc_t newFree)
{
if (newMalloc)
defaultFrameMalloc = newMalloc;

if (newFree)
defaultFrameFree = newFree;
}

/** Used to allocate a frame buffer
* This method can be overriden in subclasses to use custom memory allocation
* \param[in] size Required buffer size
* Returns pointer to buffer of size specified
*/
void* NDArrayPool::frameMalloc(size_t size)
{
return defaultFrameMalloc(size);
}

/** Used to free a frame buffer
* This method can be overriden in subclasses to use custom memory deallocation
* \param[in] ptr Pointer to memory that will be deallocated
*/
void NDArrayPool::frameFree(void *ptr)
{
defaultFrameFree(ptr);
}

/** Create new NDArray object.
* This method should be overriden by a pool class that manages objects
* that derive from NDArray class.
Expand Down Expand Up @@ -139,7 +178,7 @@ NDArray* NDArrayPool::alloc(int ndims, size_t *dims, NDDataType_t dataType, size
if (pData || (pListElement->dataSize_ > (dataSize * THRESHOLD_SIZE_RATIO))) {
// We found an array but it is too large. Set the size to 0 so it will be allocated below.
memorySize_ -= pArray->dataSize;
free(pArray->pData);
frameFree(pArray->pData);
pArray->pData = NULL;
}
freeList_.erase(pListElement);
Expand Down Expand Up @@ -193,7 +232,7 @@ NDArray* NDArrayPool::alloc(int ndims, size_t *dims, NDDataType_t dataType, size
"%s: error: reached limit of %ld memory (%d buffers)\n",
functionName, (long)maxMemory_, numBuffers_);
} else {
pArray->pData = malloc(dataSize);
pArray->pData = frameMalloc(dataSize);
if (pArray->pData) {
pArray->dataSize = dataSize;
pArray->compressedSize = dataSize;
Expand Down

0 comments on commit 5a4eaaf

Please sign in to comment.