/* vim: set expandtab ts=4 sw=4: */
/*
* You may redistribute this program and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifndef Allocator_H
#define Allocator_H
#include
#include
struct Allocator;
/**
* Writer interface which writes data to memory and
* provides pointers to the memory locations where it wrote.
*/
struct Allocator
{
/** The internal state of the Allocator. */
void* const context;
/**
* Free the heap allocations held by the allocator and any of its children.
*
* @param this the Allocator which is being called. Use: allocator->free(allocator);
*/
void (* const free)(const struct Allocator* this, const char* identFile, int identLine);
/**
* Add a function to be called when the allocator is freed.
* This helps keep track of memory allocated by third party applications
* which demand to use malloc themselves.
*
* @param callback the function to call.
* @param callbackContext the data to pass the function when calling it.
* @param this the memory allocator.
* @return a pointer which can be passed to notOnFree() to remove the job.
*/
void* (* const onFree)(void (*callback)(void* callbackContext),
void* callbackContext,
const struct Allocator* this);
/**
* Remove a function which was registered with onFree().
*
* @param job the return value from calling onFree().
* @param alloc the memory allocator.
* @return true if the job was found and removed, false otherwise.
*/
bool (* const notOnFree)(void* job, struct Allocator* alloc);
/**
* Allocate some memory from this memory allocator.
* The allocation will be aligned on the size of a pointer, if you need further alignment then
* you must handle it manually.
*
* @param numberOfBytes how much memory to allocate.
* @param this the memory allocator, use allocator->malloc(10, allocator) to allocate 10 bytes.
* @return a pointer to the newly allocated memory.
* @see malloc()
*/
void* (* const malloc)(size_t numberOfBytes,
const struct Allocator* thisAlloc,
const char* identFile,
int identLine);
/**
* Allocate some memory from this memory allocator.
* The allocation will be aligned on the size of a pointer, if you need further alignment then
* you must handle it manually.
* Memory location will be initialized to 0.
*
* @param numberOfBytes how much memory to allocate.
* @param multiplier how many times the number of bytes to allocate.
* @param this the memory allocator.
* @return a pointer to the newly allocated memory.
* @see calloc()
*/
void* (* const calloc)(size_t numberOfBytes,
size_t multiplier,
const struct Allocator* thisAlloc,
const char* identFile,
int identLine);
/**
* Allocate some memory and copy something into that memory space.
* The allocation will be aligned on the size of a pointer, if you need further alignment then
* you must handle it manually.
*
* @param numberOfBytes how much memory to allocate.
* @param thisAllocator the memory allocator.
* @param toClone a pointer to something which will be cloned into the newly allocated memory,
* if this is NULL or is not as large as numberOfBytes, undefined behavior will
* result.
* @return a pointer to the newly allocated memory.
*/
void* (* const clone)(size_t numberOfBytes,
const struct Allocator* thisAllocator,
const void* toClone,
const char* identFile,
int identLine);
/**
* Re-allocate memory so that an allocation can be expanded.
* The allocation will be aligned on the size of a pointer, if you need further alignment then
* you must handle it manually.
*
* @param originalAllocation a pointer to the original memory allocation which is to be
* reallocated.
* @param numberOfBytes how much memory to allocate.
* @param thisAllocator the memory allocator.
* @return a pointer to the newly allocated memory.
*/
void* (* const realloc)(const void* originalAllocation,
size_t numberOfBytes,
const struct Allocator* thisAllocator,
const char* identFile,
int identLine);
/**
* Get a new child of this allocator.
* When this allocator is freed all of its children will be freed as well.
*
* @param this the memory allocator, use Allocator_child(allocator) to get a child.
* @param identFile the name of the file where this was called from to aid in debugging.
* @param identLine the line number where this was called.
* @return a child allocator.
*/
struct Allocator* (* const child)(const struct Allocator* thisAlloc,
const char* identFile,
int identLine);
};
#define Allocator_clone(alloc, content) \
alloc->clone(sizeof(*content), alloc, content, __FILE__, __LINE__)
#define Allocator_malloc(alloc, size) \
alloc->malloc(size, alloc, __FILE__, __LINE__);
#define Allocator_calloc(alloc, size, count) \
alloc->calloc(size, count, alloc, __FILE__, __LINE__)
#define Allocator_onFree(alloc, callback, context) \
alloc->onFree(callback, context, alloc)
#define Allocator_notOnFree(alloc, job) \
alloc->notOnFree(job, alloc)
#define Allocator_realloc(alloc, orig, size) \
alloc->realloc(orig, size, alloc, __FILE__, __LINE__)
#define Allocator_child(alloc) \
alloc->child(alloc, __FILE__, __LINE__)
#define Allocator_free(alloc) \
alloc->free(alloc, __FILE__, __LINE__)
#endif /* MEMALLOCATOR_H */