libdatatypes 0.3.2
Abstract datatypes for C.
Loading...
Searching...
No Matches
pool.c
Go to the documentation of this file.
1/***************************************************************************
2 begin........: June 2012
3 copyright....: Sebastian Fedrau
4 email........: sebastian.fedrau@gmail.com
5 ***************************************************************************/
6
7/***************************************************************************
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License v3 as published by
10 the Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License v3 for more details.
16 ***************************************************************************/
22#include <stdlib.h>
23#include <stdio.h>
24#include <assert.h>
25
26#include "pool.h"
27
28static struct _MemoryBlock *
29_memory_pool_create_block(const MemoryPool *pool)
30{
31 assert(pool != NULL);
32
33 struct _MemoryBlock *block;
34
35 if(!(block = (struct _MemoryBlock *)malloc(sizeof(struct _MemoryBlock))))
36 {
37 perror("malloc()");
38 abort();
39 }
40
41 if(!(block->items = malloc(pool->item_size * pool->block_size)))
42 {
43 perror("malloc()");
44 abort();
45 }
46
47 block->offset = 0;
48 block->next = NULL;
49
50 return block;
51}
52
53static struct _MemoryPtrBlock *
54_memory_pool_create_ptr_block(const MemoryPool *pool)
55{
56 assert(pool != NULL);
57
58 struct _MemoryPtrBlock *block;
59
60 if(!(block = (struct _MemoryPtrBlock *)malloc(sizeof(struct _MemoryPtrBlock))))
61 {
62 perror("malloc()");
63 abort();
64 }
65
66 if(!(block->items = (void **)malloc(pool->block_size * sizeof(void *))))
67 {
68 perror("malloc()");
69 abort();
70 }
71
72 block->offset = 0;
73 block->next = NULL;
74
75 return block;
76}
77
78static void *
79_memory_pool_try_get_detached_item(MemoryPool *pool)
80{
81 assert(pool != NULL);
82
83 void *item = NULL;
84
85 if(pool->free_block)
86 {
87 assert(pool->free_block->offset > 0);
88
89 item = pool->free_block->items[--pool->free_block->offset];
90
91 if(!pool->free_block->offset)
92 {
93 struct _MemoryPtrBlock *pblock = pool->free_block;
94 pool->free_block = pblock->next;
95 free(pblock->items);
96 free(pblock);
97 }
98 }
99
100 return item;
101}
102
103static void *
104_memory_pool_try_get_current_item(const MemoryPool *pool)
105{
106 assert(pool != NULL);
107
108 void *item = NULL;
109
110 if(pool->block->offset < pool->block_size)
111 {
112 item = pool->block->items + (pool->item_size * pool->block->offset++);
113 }
114
115 return item;
116}
117
118static void *
119_memory_pool_get_item_from_new_block(MemoryPool *pool)
120{
121 assert(pool != NULL);
122
123 struct _MemoryBlock *block = _memory_pool_create_block(pool);
124 block->next = pool->block;
125 pool->block = block;
126
127 /* return first item from current block & increment offset */
128 void *item = pool->block->items;
129 ++pool->block->offset;
130
131 return item;
132}
133
134static void *
135_memory_pool_alloc(Pool *alloc)
136{
137 MemoryPool *pool = (MemoryPool *)alloc;
138
139 void *item = _memory_pool_try_get_detached_item(pool);
140
141 if (!item)
142 {
143 item = _memory_pool_try_get_current_item(pool);
144 }
145
146 if (!item)
147 {
148 item = _memory_pool_get_item_from_new_block(pool);
149 }
150
151 return item;
152}
153
154static void
155_memory_pool_free(Pool *alloc, void *item)
156{
157 MemoryPool *pool = (MemoryPool *)alloc;
158 struct _MemoryPtrBlock *cur;
159
160 if(!(cur = pool->free_block))
161 {
162 pool->free_block = cur = _memory_pool_create_ptr_block(pool);
163 }
164 else if(cur->offset == pool->block_size)
165 {
166 cur = _memory_pool_create_ptr_block(pool);
167 cur->next = pool->free_block;
168 pool->free_block = cur;
169 }
170
171 cur->items[cur->offset++] = item;
172}
173
175memory_pool_new(size_t item_size, size_t block_size)
176{
177 MemoryPool *pool;
178
179 assert(item_size > 1);
180 assert(block_size > 1);
181 assert(block_size < SIZE_MAX / item_size);
182 assert(block_size < SIZE_MAX / sizeof(void *));
183
184 if(!(pool = (MemoryPool *)malloc(sizeof(MemoryPool))))
185 {
186 perror("malloc()");
187 abort();
188 }
189
190 pool->free_block = NULL;
191 pool->item_size = item_size;
192 pool->block_size = block_size;
193 pool->block = _memory_pool_create_block(pool);
194
195 ((Pool *)pool)->alloc = _memory_pool_alloc;
196 ((Pool *)pool)->free = _memory_pool_free;
197
198 return pool;
199}
200
201void
203{
204 struct _MemoryBlock *iter;
205 struct _MemoryPtrBlock *piter;
206
207 assert(pool != NULL);
208
209 /* free memory blocks & list */
210 iter = pool->block;
211
212 while(iter)
213 {
214 struct _MemoryBlock *block;
215
216 block = iter;
217 iter = iter->next;
218 free(block->items);
219 free(block);
220 }
221
222 /* free list containing free items */
223 piter = pool->free_block;
224
225 while(piter)
226 {
227 struct _MemoryPtrBlock *pblock;
228
229 pblock = piter;
230 piter = piter->next;
231 free(pblock->items);
232 free(pblock);
233 }
234
235 free(pool);
236}
237
void memory_pool_destroy(MemoryPool *pool)
Definition pool.c:202
MemoryPool * memory_pool_new(size_t item_size, size_t block_size)
Definition pool.c:175
Allocate memory blocks of same sizes.
struct _MemoryBlock * next
Definition pool.h:63
size_t item_size
Definition pool.h:84
struct _MemoryPtrBlock * next
Definition pool.h:79
struct MemoryPool::_MemoryPtrBlock * free_block
First pointer block.
size_t block_size
Definition pool.h:82
struct MemoryPool::_MemoryBlock * block
First memory block.
This memory pool allocates blocks of memory and grows automatically.
Definition pool.h:45
Allocate groups of equal-sized chunks of memory.
Definition pool.h:33