You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
18 KiB
596 lines
18 KiB
/*-------------------------------------------------------------------------
|
|
* drawElements Memory Pool Library
|
|
* --------------------------------
|
|
*
|
|
* Copyright 2014 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*//*!
|
|
* \file
|
|
* \brief Memory pool management.
|
|
*//*--------------------------------------------------------------------*/
|
|
|
|
#include "deMemPool.h"
|
|
#include "deMemory.h"
|
|
#include "deInt32.h"
|
|
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
# include "deRandom.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
enum
|
|
{
|
|
INITIAL_PAGE_SIZE = 128, /*!< Size for the first allocated memory page. */
|
|
MAX_PAGE_SIZE = 8096, /*!< Maximum size for a memory page. */
|
|
MEM_PAGE_BASE_ALIGN = 4 /*!< Base alignment guarantee for mem page data ptr. */
|
|
};
|
|
|
|
typedef struct MemPage_s MemPage;
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \internal
|
|
* \brief Memory page header.
|
|
*
|
|
* Represent a page of memory allocate by a memory pool.
|
|
*//*--------------------------------------------------------------------*/
|
|
struct MemPage_s
|
|
{
|
|
int capacity;
|
|
int bytesAllocated;
|
|
|
|
MemPage* nextPage;
|
|
};
|
|
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
typedef struct DebugAlloc_s DebugAlloc;
|
|
|
|
struct DebugAlloc_s
|
|
{
|
|
void* memPtr;
|
|
DebugAlloc* next;
|
|
};
|
|
#endif
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Memory pool.
|
|
*
|
|
* A pool of memory from which individual memory allocations can be made.
|
|
* The memory pools don't have a freeing operation for individual allocations,
|
|
* but rather all of the memory allocated from a pool is freed when the pool
|
|
* is destroyed.
|
|
*
|
|
* The pools can be arranged into a hierarchy. If a pool with children is
|
|
* destroyed, all of the children are first recursively destroyed and then
|
|
* the pool itself.
|
|
*
|
|
* The memory pools support a feature where individual allocations can be
|
|
* made to simulate failure (i.e., return null). This can be enabled by
|
|
* creating the root pool with the deMemPool_createFailingRoot() function.
|
|
* When the feature is enabled, also creation of sub-pools occasionally
|
|
* fails.
|
|
*//*--------------------------------------------------------------------*/
|
|
struct deMemPool_s
|
|
{
|
|
deUint32 flags; /*!< Flags. */
|
|
deMemPool* parent; /*!< Pointer to parent (null for root pools). */
|
|
deMemPoolUtil* util; /*!< Utilities (callbacks etc.). */
|
|
int numChildren; /*!< Number of child pools. */
|
|
deMemPool* firstChild; /*!< Pointer to first child pool in linked list. */
|
|
deMemPool* prevPool; /*!< Previous pool in parent's linked list. */
|
|
deMemPool* nextPool; /*!< Next pool in parent's linked list. */
|
|
|
|
MemPage* currentPage; /*!< Current memory page from which to allocate. */
|
|
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
deBool allowFailing; /*!< Is allocation failure simulation enabled? */
|
|
deRandom failRandom; /*!< RNG for failing allocations. */
|
|
#endif
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
deBool enableDebugAllocs; /*!< If true, always allocates using deMalloc(). */
|
|
DebugAlloc* debugAllocListHead; /*!< List of allocation in debug mode. */
|
|
|
|
int lastAllocatedIndex; /*!< Index of last allocated pool (rootPool only). */
|
|
int allocIndex; /*!< Allocation index (running counter). */
|
|
#endif
|
|
#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
|
|
int maxMemoryAllocated; /*!< Maximum amount of memory allocated from pools. */
|
|
int maxMemoryCapacity; /*!< Maximum amount of memory allocated for pools. */
|
|
#endif
|
|
};
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \internal
|
|
* \brief Initialize a memory page.
|
|
* \param page Memory page to initialize.
|
|
* \param capacity Capacity allocated for the memory page.
|
|
*//*--------------------------------------------------------------------*/
|
|
static void MemPage_init (MemPage* page, size_t capacity)
|
|
{
|
|
memset(page, 0, sizeof(MemPage));
|
|
#if defined(DE_DEBUG)
|
|
memset(page + 1, 0xCD, capacity);
|
|
#endif
|
|
page->capacity = (int)capacity;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \internal
|
|
* \brief Create a new memory page.
|
|
* \param capacity Capacity for the memory page.
|
|
* \return The created memory page (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
static MemPage* MemPage_create (size_t capacity)
|
|
{
|
|
MemPage* page = (MemPage*)deMalloc(sizeof(MemPage) + capacity);
|
|
if (!page)
|
|
return DE_NULL;
|
|
|
|
DE_ASSERT(deIsAlignedPtr(page+1, MEM_PAGE_BASE_ALIGN));
|
|
|
|
MemPage_init(page, capacity);
|
|
return page;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \internal
|
|
* \brief Destroy a memory page.
|
|
* \param page Memory page to destroy.
|
|
*//*--------------------------------------------------------------------*/
|
|
static void MemPage_destroy (MemPage* page)
|
|
{
|
|
#if defined(DE_DEBUG)
|
|
/* Fill with garbage to hopefully catch dangling pointer bugs easier. */
|
|
deUint8* dataPtr = (deUint8*)(page + 1);
|
|
memset(dataPtr, 0xCD, (size_t)page->capacity);
|
|
#endif
|
|
deFree(page);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \internal
|
|
* \brief Internal function for creating a new memory pool.
|
|
* \param parent Parent pool (may be null).
|
|
* \return The created memory pool (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
static deMemPool* createPoolInternal (deMemPool* parent)
|
|
{
|
|
deMemPool* pool;
|
|
MemPage* initialPage;
|
|
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
if (parent && parent->allowFailing)
|
|
{
|
|
if ((deRandom_getUint32(&parent->failRandom) & 16383) <= 15)
|
|
return DE_NULL;
|
|
}
|
|
#endif
|
|
|
|
/* Init first page. */
|
|
initialPage = MemPage_create(INITIAL_PAGE_SIZE);
|
|
if (!initialPage)
|
|
return DE_NULL;
|
|
|
|
/* Alloc pool from initial page. */
|
|
DE_ASSERT((int)sizeof(deMemPool) <= initialPage->capacity);
|
|
pool = (deMemPool*)(initialPage + 1);
|
|
initialPage->bytesAllocated += (int)sizeof(deMemPool);
|
|
|
|
memset(pool, 0, sizeof(deMemPool));
|
|
pool->currentPage = initialPage;
|
|
|
|
/* Register to parent. */
|
|
pool->parent = parent;
|
|
if (parent)
|
|
{
|
|
parent->numChildren++;
|
|
if (parent->firstChild) parent->firstChild->prevPool = pool;
|
|
pool->nextPool = parent->firstChild;
|
|
parent->firstChild = pool;
|
|
}
|
|
|
|
/* Get utils from parent. */
|
|
pool->util = parent ? parent->util : DE_NULL;
|
|
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
pool->allowFailing = parent ? parent->allowFailing : DE_FALSE;
|
|
deRandom_init(&pool->failRandom, parent ? deRandom_getUint32(&parent->failRandom) : 0x1234abcd);
|
|
#endif
|
|
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
pool->enableDebugAllocs = parent ? parent->enableDebugAllocs : DE_FALSE;
|
|
pool->debugAllocListHead = DE_NULL;
|
|
|
|
/* Pool allocation index. */
|
|
{
|
|
deMemPool* root = pool;
|
|
while (root->parent)
|
|
root = root->parent;
|
|
|
|
if (pool == root)
|
|
root->lastAllocatedIndex = 0;
|
|
|
|
pool->allocIndex = ++root->lastAllocatedIndex;
|
|
|
|
/* \note Put the index of leaking pool here and add a breakpoint to catch leaks easily. */
|
|
/* if (pool->allocIndex == 51)
|
|
root = root;*/
|
|
}
|
|
#endif
|
|
|
|
return pool;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Create a new root memory pool.
|
|
* \return The created memory pool (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
deMemPool* deMemPool_createRoot (const deMemPoolUtil* util, deUint32 flags)
|
|
{
|
|
deMemPool* pool = createPoolInternal(DE_NULL);
|
|
if (!pool)
|
|
return DE_NULL;
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
if (flags & DE_MEMPOOL_ENABLE_FAILING_ALLOCS)
|
|
pool->allowFailing = DE_TRUE;
|
|
#endif
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
if (flags & DE_MEMPOOL_ENABLE_DEBUG_ALLOCS)
|
|
{
|
|
pool->enableDebugAllocs = DE_TRUE;
|
|
pool->debugAllocListHead = DE_NULL;
|
|
}
|
|
#endif
|
|
DE_UNREF(flags); /* in case no debug features enabled */
|
|
|
|
/* Get copy of utilities. */
|
|
if (util)
|
|
{
|
|
deMemPoolUtil* utilCopy = DE_POOL_NEW(pool, deMemPoolUtil);
|
|
DE_ASSERT(util->allocFailCallback);
|
|
if (!utilCopy)
|
|
{
|
|
deMemPool_destroy(pool);
|
|
return DE_NULL;
|
|
}
|
|
|
|
memcpy(utilCopy, util, sizeof(deMemPoolUtil));
|
|
pool->util = utilCopy;
|
|
}
|
|
|
|
return pool;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Create a sub-pool for an existing memory pool.
|
|
* \return The created memory pool (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
deMemPool* deMemPool_create (deMemPool* parent)
|
|
{
|
|
deMemPool* pool;
|
|
DE_ASSERT(parent);
|
|
pool = createPoolInternal(parent);
|
|
if (!pool && parent->util)
|
|
parent->util->allocFailCallback(parent->util->userPointer);
|
|
return pool;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Destroy a memory pool.
|
|
* \param pool Pool to be destroyed.
|
|
*
|
|
* Frees all the memory allocated from the pool. Also destroyed any child
|
|
* pools that the pool has (recursively).
|
|
*//*--------------------------------------------------------------------*/
|
|
void deMemPool_destroy (deMemPool* pool)
|
|
{
|
|
deMemPool* iter;
|
|
deMemPool* iterNext;
|
|
|
|
#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
|
|
/* Update memory consumption statistics. */
|
|
if (pool->parent)
|
|
{
|
|
deMemPool* root = pool->parent;
|
|
while (root->parent)
|
|
root = root->parent;
|
|
root->maxMemoryAllocated = deMax32(root->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(root, DE_TRUE));
|
|
root->maxMemoryCapacity = deMax32(root->maxMemoryCapacity, deMemPool_getCapacity(root, DE_TRUE));
|
|
}
|
|
#endif
|
|
|
|
/* Destroy all children. */
|
|
iter = pool->firstChild;
|
|
while (iter)
|
|
{
|
|
iterNext = iter->nextPool;
|
|
deMemPool_destroy(iter);
|
|
iter = iterNext;
|
|
}
|
|
|
|
DE_ASSERT(pool->numChildren == 0);
|
|
|
|
/* Update pointers. */
|
|
if (pool->prevPool) pool->prevPool->nextPool = pool->nextPool;
|
|
if (pool->nextPool) pool->nextPool->prevPool = pool->prevPool;
|
|
|
|
if (pool->parent)
|
|
{
|
|
deMemPool* parent = pool->parent;
|
|
if (parent->firstChild == pool)
|
|
parent->firstChild = pool->nextPool;
|
|
|
|
parent->numChildren--;
|
|
DE_ASSERT(parent->numChildren >= 0);
|
|
}
|
|
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
/* Free all debug allocations. */
|
|
if (pool->enableDebugAllocs)
|
|
{
|
|
DebugAlloc* alloc = pool->debugAllocListHead;
|
|
DebugAlloc* next;
|
|
|
|
while (alloc)
|
|
{
|
|
next = alloc->next;
|
|
deAlignedFree(alloc->memPtr);
|
|
deFree(alloc);
|
|
alloc = next;
|
|
}
|
|
|
|
pool->debugAllocListHead = DE_NULL;
|
|
}
|
|
#endif
|
|
|
|
/* Free pages. */
|
|
/* \note Pool itself is allocated from first page, so we must not touch the pool after freeing the page! */
|
|
{
|
|
MemPage* page = pool->currentPage;
|
|
MemPage* nextPage;
|
|
|
|
while (page)
|
|
{
|
|
nextPage = page->nextPage;
|
|
MemPage_destroy(page);
|
|
page = nextPage;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Get the number of children for a pool.
|
|
* \return The number of (immediate) child pools a memory pool has.
|
|
*//*--------------------------------------------------------------------*/
|
|
int deMemPool_getNumChildren (const deMemPool* pool)
|
|
{
|
|
return pool->numChildren;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Get the number of bytes allocated (by the user) from the pool.
|
|
* \param pool Pool pointer.
|
|
* \param recurse Is operation recursive to child pools?
|
|
* \return The number of bytes allocated by the pool (including child pools
|
|
* if 'recurse' is true).
|
|
*//*--------------------------------------------------------------------*/
|
|
int deMemPool_getNumAllocatedBytes (const deMemPool* pool, deBool recurse)
|
|
{
|
|
int numAllocatedBytes = 0;
|
|
MemPage* memPage;
|
|
|
|
for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
|
|
numAllocatedBytes += memPage->bytesAllocated;
|
|
|
|
if (recurse)
|
|
{
|
|
deMemPool* child;
|
|
for (child = pool->firstChild; child; child = child->nextPool)
|
|
numAllocatedBytes += deMemPool_getNumAllocatedBytes(child, DE_TRUE);
|
|
}
|
|
|
|
return numAllocatedBytes;
|
|
}
|
|
|
|
int deMemPool_getCapacity (const deMemPool* pool, deBool recurse)
|
|
{
|
|
int numCapacityBytes = 0;
|
|
MemPage* memPage;
|
|
|
|
for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
|
|
numCapacityBytes += memPage->capacity;
|
|
|
|
if (recurse)
|
|
{
|
|
deMemPool* child;
|
|
for (child = pool->firstChild; child; child = child->nextPool)
|
|
numCapacityBytes += deMemPool_getCapacity(child, DE_TRUE);
|
|
}
|
|
|
|
return numCapacityBytes;
|
|
}
|
|
|
|
DE_INLINE void* deMemPool_allocInternal (deMemPool* pool, size_t numBytes, deUint32 alignBytes)
|
|
{
|
|
MemPage* curPage = pool->currentPage;
|
|
|
|
#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
|
|
if (pool->allowFailing)
|
|
{
|
|
if ((deRandom_getUint32(&pool->failRandom) & 16383) <= 15)
|
|
return DE_NULL;
|
|
}
|
|
#endif
|
|
|
|
#if defined(DE_SUPPORT_DEBUG_POOLS)
|
|
if (pool->enableDebugAllocs)
|
|
{
|
|
DebugAlloc* header = DE_NEW(DebugAlloc);
|
|
void* ptr = deAlignedMalloc(numBytes, alignBytes);
|
|
|
|
if (!header || !ptr)
|
|
{
|
|
deFree(header);
|
|
deAlignedFree(ptr);
|
|
return DE_NULL;
|
|
}
|
|
|
|
header->memPtr = ptr;
|
|
header->next = pool->debugAllocListHead;
|
|
pool->debugAllocListHead = header;
|
|
|
|
return ptr;
|
|
}
|
|
#endif
|
|
|
|
DE_ASSERT(curPage);
|
|
DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
|
|
{
|
|
void* curPagePtr = (void*)((deUint8*)(curPage + 1) + curPage->bytesAllocated);
|
|
void* alignedPtr = deAlignPtr(curPagePtr, alignBytes);
|
|
size_t alignPadding = (size_t)((deUintptr)alignedPtr - (deUintptr)curPagePtr);
|
|
|
|
if (numBytes + alignPadding > (size_t)(curPage->capacity - curPage->bytesAllocated))
|
|
{
|
|
/* Does not fit to current page. */
|
|
int maxAlignPadding = deMax32(0, ((int)alignBytes)-MEM_PAGE_BASE_ALIGN);
|
|
int newPageCapacity = deMax32(deMin32(2*curPage->capacity, MAX_PAGE_SIZE), ((int)numBytes)+maxAlignPadding);
|
|
|
|
curPage = MemPage_create((size_t)newPageCapacity);
|
|
if (!curPage)
|
|
return DE_NULL;
|
|
|
|
curPage->nextPage = pool->currentPage;
|
|
pool->currentPage = curPage;
|
|
|
|
DE_ASSERT(curPage->bytesAllocated == 0);
|
|
|
|
curPagePtr = (void*)(curPage + 1);
|
|
alignedPtr = deAlignPtr(curPagePtr, alignBytes);
|
|
alignPadding = (size_t)((deUintptr)alignedPtr - (deUintptr)curPagePtr);
|
|
|
|
DE_ASSERT(numBytes + alignPadding <= (size_t)curPage->capacity);
|
|
}
|
|
|
|
curPage->bytesAllocated += (int)(numBytes + alignPadding);
|
|
return alignedPtr;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Allocate memory from a pool.
|
|
* \param pool Memory pool to allocate from.
|
|
* \param numBytes Number of bytes to allocate.
|
|
* \return Pointer to the allocate memory (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
void* deMemPool_alloc (deMemPool* pool, size_t numBytes)
|
|
{
|
|
void* ptr;
|
|
DE_ASSERT(pool);
|
|
DE_ASSERT(numBytes > 0);
|
|
ptr = deMemPool_allocInternal(pool, numBytes, DE_POOL_DEFAULT_ALLOC_ALIGNMENT);
|
|
if (!ptr && pool->util)
|
|
pool->util->allocFailCallback(pool->util->userPointer);
|
|
return ptr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Allocate aligned memory from a pool.
|
|
* \param pool Memory pool to allocate from.
|
|
* \param numBytes Number of bytes to allocate.
|
|
* \param alignBytes Required alignment in bytes, must be power of two.
|
|
* \return Pointer to the allocate memory (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
void* deMemPool_alignedAlloc (deMemPool* pool, size_t numBytes, deUint32 alignBytes)
|
|
{
|
|
void* ptr;
|
|
DE_ASSERT(pool);
|
|
DE_ASSERT(numBytes > 0);
|
|
DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
|
|
ptr = deMemPool_allocInternal(pool, numBytes, alignBytes);
|
|
DE_ASSERT(deIsAlignedPtr(ptr, alignBytes));
|
|
if (!ptr && pool->util)
|
|
pool->util->allocFailCallback(pool->util->userPointer);
|
|
return ptr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Duplicate a piece of memory into a memory pool.
|
|
* \param pool Memory pool to allocate from.
|
|
* \param ptr Piece of memory to duplicate.
|
|
* \return Pointer to the copied memory block (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
void* deMemPool_memDup (deMemPool* pool, const void* ptr, size_t numBytes)
|
|
{
|
|
void* newPtr = deMemPool_alloc(pool, numBytes);
|
|
if (newPtr)
|
|
memcpy(newPtr, ptr, numBytes);
|
|
return newPtr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Duplicate a string into a memory pool.
|
|
* \param pool Memory pool to allocate from.
|
|
* \param str String to duplicate.
|
|
* \return Pointer to the new string (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
char* deMemPool_strDup (deMemPool* pool, const char* str)
|
|
{
|
|
size_t len = strlen(str);
|
|
char* newStr = (char*)deMemPool_alloc(pool, len+1);
|
|
if (newStr)
|
|
memcpy(newStr, str, len+1);
|
|
return newStr;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*//*!
|
|
* \brief Duplicate a string into a memory pool, with a maximum length.
|
|
* \param pool Memory pool to allocate from.
|
|
* \param str String to duplicate.
|
|
* \param maxLength Maximum number of characters to duplicate.
|
|
* \return Pointer to the new string (or null on failure).
|
|
*//*--------------------------------------------------------------------*/
|
|
char* deMemPool_strnDup (deMemPool* pool, const char* str, int maxLength)
|
|
{
|
|
size_t len = (size_t)deMin32((int)strlen(str), deMax32(0, maxLength));
|
|
char* newStr = (char*)deMemPool_alloc(pool, len + 1);
|
|
|
|
DE_ASSERT(maxLength >= 0);
|
|
|
|
if (newStr)
|
|
{
|
|
memcpy(newStr, str, len);
|
|
newStr[len] = 0;
|
|
}
|
|
return newStr;
|
|
}
|
|
|
|
#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
|
|
|
|
int deMemPool_getMaxNumAllocatedBytes (const deMemPool* pool)
|
|
{
|
|
DE_ASSERT(pool && !pool->parent); /* must be root */
|
|
return deMax32(pool->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(pool, DE_TRUE));
|
|
}
|
|
|
|
int deMemPool_getMaxCapacity (const deMemPool* pool)
|
|
{
|
|
DE_ASSERT(pool && !pool->parent); /* must be root */
|
|
return deMax32(pool->maxMemoryCapacity, deMemPool_getCapacity(pool, DE_TRUE));
|
|
}
|
|
|
|
#endif
|