Skip to content

Instantly share code, notes, and snippets.

@pidhii
Last active October 25, 2019 10:25
Show Gist options
  • Save pidhii/4b98cb5dcfa78bb0211e37ab1f8a0f78 to your computer and use it in GitHub Desktop.
Save pidhii/4b98cb5dcfa78bb0211e37ab1f8a0f78 to your computer and use it in GitHub Desktop.
Uniform allocator in C.
/*
* Usage example:
* ```
* #define UALLOC_NAME ASD
* #define UALLOC_TYPE struct my_data
* #incldude "uniform_allocator.h"
*
* ...
* struct ualloc_ASD alloc;
* // initialize
* ualloc_ASD_init(&alloc);
* // allocation
* struct my_data* ptr = ualloc_ASD_alloc(&alloc);
* ...
* // deallocation
* ualloc_ASD_free(&alloc, ptr);
* // release memory pools
* ualloc_ASD_destroy(&alloc);
* ```
*
* Note:
* Requires my "vector.h".
* You can get it from <https://gist.github.com/pidhii/91a86b1c58816d0fa010083967666ed6>.
*/
#ifndef UALLOC_POOL_SIZE
#define UALLOC_POOL_SIZE 0x4000
#endif
#define _UALLOC_CONCAT(x, y) x##y
#define _UALLOC_CONCAT3(x, y, z) x##y##z
#define _UALLOC_CONCAT4(x, y, z, k) x##y##z##k
#define _UALLOC_APPLY(macro, ...) macro(__VA_ARGS__)
#define _UALLOC_CELL union _UALLOC_APPLY(_UALLOC_CONCAT, ualloc_cell_, UALLOC_NAME)
#define _UALLOC_POOL struct _UALLOC_APPLY(_UALLOC_CONCAT, ualloc_pool_, UALLOC_NAME)
#define _UALLOC struct _UALLOC_APPLY(_UALLOC_CONCAT, ualloc_, UALLOC_NAME)
#define _UALLOC_METHOD(method) _UALLOC_APPLY(_UALLOC_CONCAT4, ualloc_, UALLOC_NAME, _ , method)
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
_UALLOC_CELL
{
UALLOC_TYPE data;
_UALLOC_CELL* next_free;
};
_UALLOC_POOL
{
_UALLOC_CELL* pool;
size_t size; /* Number of currently available free cells. */
};
#define _UALLOC_POOLS_VEC _UALLOC_APPLY(_UALLOC_CONCAT3, ualloc_pools, _, UALLOC_NAME)
#define VECTOR_FULL_NAME _UALLOC_POOLS_VEC
#define VECTOR_TYPE _UALLOC_POOL
#include "vector.h"
_UALLOC
{
size_t npools;
struct _UALLOC_POOLS_VEC pools;
_UALLOC_POOL* curpool;
_UALLOC_CELL* free_cell; /* Pointer to some free cell, or NULL. */
};
static __inline__
void _UALLOC_METHOD(init_pool)(_UALLOC_POOL* pool)
{
pool->pool = malloc(UALLOC_POOL_SIZE * sizeof(_UALLOC_CELL));
assert(pool->pool);
pool->size = 0;
}
static
void _UALLOC_METHOD(destroy_pool)(_UALLOC_POOL* pool)
{ free(pool->pool); }
void _UALLOC_METHOD(init)(_UALLOC* ua)
{
_UALLOC_APPLY(_UALLOC_CONCAT, _UALLOC_POOLS_VEC, _init)(&ua->pools);
ua->curpool =
_UALLOC_APPLY(_UALLOC_CONCAT, _UALLOC_POOLS_VEC, _push_back)(&ua->pools);
_UALLOC_METHOD(init_pool)(ua->curpool);
}
void _UALLOC_METHOD(destroy)(_UALLOC* ua)
{
size_t i;
for (i = 0; i < ua->pools.size; ++i)
_UALLOC_METHOD(destroy_pool)(&ua->pools.data[i]);
_UALLOC_APPLY(_UALLOC_CONCAT, _UALLOC_POOLS_VEC, _destroy) (&ua->pools);
}
static __inline__
UALLOC_TYPE* _UALLOC_METHOD(alloc)(_UALLOC* ua)
{
_UALLOC_CELL *tmp;
if ((tmp = ua->free_cell)) {
ua->free_cell = tmp->next_free;
return (void*)tmp;
}
if (ua->curpool->size == UALLOC_POOL_SIZE) {
/* allocate new pool */
ua->curpool =
_UALLOC_APPLY(_UALLOC_CONCAT, _UALLOC_POOLS_VEC, _push_back)(&ua->pools);
_UALLOC_METHOD(init_pool)(ua->curpool);
}
return (void*)(ua->curpool->pool + ua->curpool->size++);
}
static __inline__
int _UALLOC_METHOD(free)(_UALLOC* ua, UALLOC_TYPE* ptr)
{
((_UALLOC_CELL*)ptr)->next_free = ua->free_cell;
ua->free_cell = (void*)ptr;
return 0;
}
#undef _UALLOC_CONCAT
#undef _UALLOC_CONCAT3
#undef _UALLOC_CONCAT4
#undef _UALLOC_APPLY
#undef _UALLOC_CELL
#undef _UALLOC_POOL
#undef _UALLOC
#undef _UALLOC_METHOD
#undef UALLOC_POOL_SIZE
#undef UALLOC_TYPE
#undef UALLOC_NAME
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment