1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
/* A block of memory for 20-bytes string (+ nul byte). */
typedef struct mem_block {
struct mem_block* next;
char data[21];
} mem_block;
/* A memory pool. */
typedef struct mem_pool {
mem_block* pool;
mem_block* free_list;
} mem_pool;
void init_pool(mem_pool* pool, size_t nb_block);
void* alloc(mem_pool* pool);
void dealloc(mem_pool* pool, void* data);
void destroy_pool(mem_pool* pool);
/* Create a pool of `nb_block` objects. */
void init_pool(mem_pool* pool, size_t nb_block)
{
mem_block* blk;
mem_block* end;
mem_block* last;
assert (nb_block > 0);
/* Allocate the pool. */
pool->pool = malloc(nb_block * sizeof(mem_block));
pool->free_list = pool->pool;
end = pool->free_list + nb_block;
last = end - 1;
/* Put all the blocks in the free list. */
for (blk = pool->free_list; blk < last; ++blk) {
blk->next = blk + 1;
}
last->next = NULL;
}
/* Return memory for one object, or NULL if the pool is exhausted. */
void* alloc(mem_pool *pool)
{
mem_block* blk;
assert (pool);
/* Pool exhausted. */
if (pool->free_list == NULL) {
return NULL;
}
/* Take the first free block. */
blk = pool->free_list;
pool->free_list = pool->free_list->next;
return blk->data;
}
/* Free one object. */
void dealloc(mem_pool *pool, void* data)
{
assert (pool);
if (data) {
/* Add the block in the free list. */
mem_block* blk = ((mem_block*)((char*)(data) - offsetof(mem_block, data)));
blk->next = pool->free_list;
pool->free_list = blk;
}
}
/* Destroy the pool and free the underlying memory. */
void destroy_pool(mem_pool* pool)
{
assert (pool);
if (pool->pool != NULL) {
/* Free the whole pool. */
free(pool->pool);
pool->pool = NULL;
pool->free_list = NULL;
}
}
/* Little test. */
int main(void)
{
mem_pool pool;
char* s1;
char* s2;
char* s3;
char* s4;
/* Create a pool for 3 strings */
init_pool(&pool, 3);
/* The first 3 allocations should success. */
s1 = alloc(&pool);
s2 = alloc(&pool);
s3 = alloc(&pool);
assert (s1 != NULL);
assert (s2 != NULL);
assert (s3 != NULL);
strcpy(s1, "Hello");
strcpy(s2, "World");
strcpy(s3, "!");
assert (strcmp(s1, "Hello") == 0);
assert (strcmp(s2, "World") == 0);
assert (strcmp(s3, "!") == 0);
/* The 4th allocation should fail. */
s4 = alloc(&pool);
assert (s4 == NULL);
/* Free s3, the allocation of s4 is now possible. */
dealloc(&pool, s3);
s4 = alloc(&pool);
assert (s4 != NULL);
strcpy(s4, "?");
assert (strcmp(s4, "?") == 0);
/* Wipe the whole pool, don't need to wipe string by string. */
destroy_pool(&pool);
assert (pool.pool == NULL);
assert (pool.free_list== NULL);
return 0;
} |
Partager