123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #include <ell/mempool.h>
- #include <assert.h>
- #include <stdio.h>
- #include <string.h>
- #ifndef ELL_MEMPOOL_DEFAULT_RESERVE
- #define ELL_MEMPOOL_DEFAULT_RESERVE 0
- #endif
- #ifndef ELL_MEMPOOL_DEFAULT_CHUNK_SIZE
- #define ELL_MEMPOOL_DEFAULT_CHUNK_SIZE 1024
- #endif
- #if ELL_MEMPOOL_DEFAULT_RESERVE < 0
- #error "negative ELL_MEMPOOL_DEFAULT_RESERVE"
- #endif
- #if ELL_MEMPOOL_DEFAULT_CHUNK_SIZE <= 0
- #error "non-positive ELL_MEMPOOL_DEFAULT_CHUNK_SIZE"
- #endif
- struct ell__mempool_chunk {
- struct ell__mempool_chunk* next_chunk;
- size_t chunk_size;
- void* data;
- };
- static void ell__mempool_add_chunk(struct ell_mempool* pool)
- {
- struct ell__mempool_chunk* chunk = malloc(sizeof(struct ell__mempool_chunk));
- chunk->data = malloc(pool->element_size * pool->chunk_size);
- chunk->next_chunk = pool->chunks;
- chunk->chunk_size = pool->chunk_size;
- pool->capacity += pool->chunk_size;
- pool->chunks = chunk;
- pool->size += pool->chunk_size;
- for (unsigned int i = 0; i < pool->chunk_size; i++) {
- ell_mempool_ret(pool, chunk->data + i * pool->element_size);
- }
- }
- /* Interface implementation */
- void ell_mempool_init(struct ell_mempool* pool, size_t element_size)
- {
- ell_mempool_init3(
- pool, element_size, ELL_MEMPOOL_DEFAULT_RESERVE, ELL_MEMPOOL_DEFAULT_CHUNK_SIZE);
- }
- void ell_mempool_init2(struct ell_mempool* pool, size_t element_size, size_t reserve)
- {
- ell_mempool_init3(pool, element_size, reserve, ELL_MEMPOOL_DEFAULT_CHUNK_SIZE);
- }
- void ell_mempool_init3(struct ell_mempool* pool,
- size_t element_size,
- size_t reserve,
- size_t chunk_size)
- {
- if (pool == NULL) {
- return;
- }
- /*
- * Leaky implementation detail:
- * The freelist is composed of pointers stored in element locations,
- * therefore an element must at least be able to hold one pointer.
- */
- if (element_size < sizeof(void*)) {
- fprintf(stderr,
- "%s: illegal ELEMENT SIZE of %ld, at least size of %ld required\n",
- __func__,
- element_size,
- sizeof(void*));
- abort();
- }
- memset(pool, 0, sizeof(*pool));
- pool->element_size = element_size;
- pool->chunk_size = chunk_size;
- pool->num_chunks = 0;
- pool->capacity = 0;
- pool->size = 0;
- pool->chunks = NULL;
- pool->next_free = NULL;
- /* allocate initial chunks */
- ell_mempool_reserve(pool, reserve);
- }
- void ell_mempool_free(struct ell_mempool* pool)
- {
- assert(pool != NULL);
- struct ell__mempool_chunk* chunk = pool->chunks;
- struct ell__mempool_chunk* tmp;
- while (chunk != NULL) {
- tmp = chunk->next_chunk;
- free(chunk->data);
- free(chunk);
- chunk = tmp;
- }
- }
- void ell_mempool_reserve(struct ell_mempool* pool, size_t reserve)
- {
- assert(pool != NULL);
- if (pool->capacity >= reserve) {
- return;
- }
- size_t required = reserve - pool->capacity;
- size_t required_chunks = required / pool->chunk_size + (required % pool->chunk_size ? 1 : 0);
- for (size_t i = 0; i < required_chunks; i++) {
- ell__mempool_add_chunk(pool);
- }
- }
- /* Memory management */
- void* ell_mempool_get(struct ell_mempool* pool)
- {
- assert(pool != NULL);
- while (pool->capacity <= pool->size) {
- ell__mempool_add_chunk(pool);
- }
- void* ptr = pool->next_free;
- pool->next_free = *((void**)ptr);
- pool->size++;
- return ptr;
- }
- void ell_mempool_ret(struct ell_mempool* pool, void* ptr)
- {
- assert(pool != NULL);
- *((void**)ptr) = pool->next_free;
- pool->next_free = ptr;
- pool->size--;
- }
- /* Queries */
- size_t ell_mempool_size(const struct ell_mempool* pool)
- {
- assert(pool != NULL);
- return pool->size;
- }
- size_t ell_mempool_capacity(const struct ell_mempool* pool)
- {
- assert(pool != NULL);
- return pool->capacity;
- }
|