Quash Shell  0.1
A simple yet powerfull shell program
 All Classes Files Functions Variables Typedefs Enumerations Macros
memory_pool.h
Go to the documentation of this file.
1 
20 #ifndef SRC_PARSING_MEMORY_POOL_H
21 #define SRC_PARSING_MEMORY_POOL_H
22 
23 #include <stdlib.h>
24 
25 #include "deque.h"
26 
33 void initialize_memory_pool(size_t size);
34 
45 void* memory_pool_alloc(size_t size);
46 
50 void destroy_memory_pool();
51 
60 char* memory_pool_strdup(const char* str);
61 
74 #define IMPLEMENT_DEQUE_MEMORY_POOL(struct_name, type) \
75  \
76  void apply_##struct_name(struct_name*, void (*)(type)); \
77  \
78  struct_name new_##struct_name(size_t init_cap) { \
79  struct_name ret; \
80  \
81  if (init_cap > 0) \
82  ret.cap = init_cap; \
83  else \
84  ret.cap = 1; \
85  \
86  ret.data = (type*) memory_pool_alloc(ret.cap * sizeof(type)); \
87  \
88  if (ret.data == NULL) { \
89  fprintf(stderr, "ERROR: Failed to reallocate struct_name" \
90  " contents"); \
91  abort(); \
92  } \
93  \
94  ret.front = ret.back = 0; \
95  ret.destructor = NULL; \
96  \
97  return ret; \
98  } \
99  \
100  struct_name new_destructable_##struct_name(size_t init_cap, \
101  void (*destructor)(type)){ \
102  struct_name ret = new_##struct_name(init_cap); \
103  ret.destructor = destructor; \
104  return ret; \
105  } \
106  \
107  void destroy_##struct_name(struct_name* deq) { \
108  assert(deq != NULL); \
109  \
110  if (deq->data == NULL) \
111  return; \
112  \
113  if (deq->destructor != NULL) \
114  apply_##struct_name(deq, deq->destructor); \
115  \
116  deq->data = NULL; \
117  deq->cap = 0; \
118  deq->front = deq->back = 0; \
119  } \
120  \
121  void empty_##struct_name(struct_name* deq) { \
122  assert(deq != NULL); \
123  assert(deq->data != NULL); /* Make sure the structure is valid */ \
124  \
125  if (deq->destructor != NULL) \
126  apply_##struct_name(deq, deq->destructor); \
127  \
128  deq->front = deq->back = 0; \
129  } \
130  \
131  bool is_empty_##struct_name(struct_name* deq) { \
132  assert(deq != NULL); \
133  assert(deq->data != NULL); /* Make sure the structure is valid */ \
134  return deq->front == deq->back; \
135  } \
136  \
137  size_t length_##struct_name(struct_name* deq) { \
138  assert(deq != NULL); \
139  assert(deq->data != NULL); /* Make sure the structure is valid */ \
140  return (deq->back - deq->front + deq->cap) % deq->cap; \
141  } \
142  \
143  static void __reallign_##struct_name(struct_name* deq) { \
144  assert(deq != NULL); \
145  assert(deq->data != NULL); /* Make sure the structure is valid */ \
146  \
147  if (deq->front != 0) { \
148  type* old_data = deq->data; \
149  size_t len = length_##struct_name(deq); \
150  \
151  deq->data = (type*) memory_pool_alloc(deq->cap * sizeof(type)); \
152  \
153  if (deq->data == NULL) { \
154  fprintf(stderr, "ERROR: Failed to reallocate struct_name" \
155  " contents"); \
156  abort(); \
157  } \
158  \
159  size_t i; \
160  \
161  for (i = 0; i < len; ++i) \
162  deq->data[i] = old_data[(deq->front + i) % deq->cap]; \
163  \
164  deq->front = 0; \
165  deq->back = i; \
166  } \
167  } \
168  \
169  type* as_array_##struct_name(struct_name* deq, size_t* len) { \
170  assert(deq != NULL); \
171  assert(deq->data != NULL); /* Make sure the structure is valid */ \
172  \
173  __reallign_##struct_name(deq); \
174  \
175  type* ret = deq->data; \
176  \
177  if (len != NULL) \
178  *len = length_##struct_name(deq); \
179  \
180  deq->data = NULL; \
181  deq->cap = deq->front = deq->back = 0; \
182  \
183  return ret; \
184  } \
185  \
186  void apply_##struct_name(struct_name* deq, void (*func)(type)) { \
187  assert(deq != NULL); \
188  assert(deq->data != NULL); /* Make sure the structure is valid */ \
189  \
190  size_t len = length_##struct_name(deq); \
191  \
192  for (size_t i = 0; i < len; ++i) { \
193  func(deq->data[(deq->front + i) % deq->cap]); \
194  } \
195  } \
196  \
197  static void __on_push_##struct_name(struct_name* deq) { \
198  if (deq->front == (deq->back + 1) % deq->cap) { \
199  type* old_data = deq->data; \
200  size_t old_cap = deq->cap; \
201  \
202  deq->cap = 2 * deq->cap; \
203  deq->data = (type*) memory_pool_alloc(deq->cap * sizeof(type)); \
204  \
205  if (deq->data == NULL) { \
206  fprintf(stderr, "ERROR: Failed to reallocate struct_name" \
207  " contents\n"); \
208  abort(); \
209  } \
210  \
211  size_t i; \
212  \
213  for (i = 0; i < old_cap - 1; ++i) \
214  deq->data[i] = old_data[(deq->front + i) % old_cap]; \
215  \
216  deq->front = 0; \
217  deq->back = i; \
218  } \
219  } \
220  \
221  static void __on_pop_##struct_name(struct_name* deq) { \
222  if (is_empty_##struct_name(deq)) { \
223  fprintf(stderr, "ERROR: Cannot pop from of struct_name while it " \
224  "is empty\n"); \
225  abort(); \
226  } \
227  } \
228  \
229  void push_front_##struct_name(struct_name* deq, type element) { \
230  assert(deq != NULL); \
231  assert(deq->data != NULL); /* Make sure the structure is valid */ \
232  __on_push_##struct_name(deq); \
233  deq->front = (deq->front + deq->cap - 1) % deq->cap; \
234  deq->data[deq->front] = element; \
235  } \
236  \
237  void push_back_##struct_name(struct_name* deq, type element) { \
238  assert(deq != NULL); \
239  assert(deq->data != NULL); /* Make sure the structure is valid */ \
240  __on_push_##struct_name(deq); \
241  deq->data[deq->back] = element; \
242  deq->back = (deq->back + 1) % deq->cap; \
243  } \
244  \
245  type pop_front_##struct_name(struct_name* deq) { \
246  assert(deq != NULL); \
247  assert(deq->data != NULL); /* Make sure the structure is valid */ \
248  __on_pop_##struct_name(deq); \
249  size_t old_front = deq->front; \
250  deq->front = (deq->front + 1) % deq->cap; \
251  return deq->data[old_front]; \
252  } \
253  \
254  type pop_back_##struct_name(struct_name* deq) { \
255  assert(deq != NULL); \
256  assert(deq->data != NULL); /* Make sure the structure is valid */ \
257  __on_pop_##struct_name(deq); \
258  deq->back = (deq->back + deq->cap - 1) % deq->cap; \
259  return deq->data[deq->back]; \
260  } \
261  \
262  type peek_front_##struct_name(struct_name* deq) { \
263  assert(deq != NULL); \
264  assert(deq->data != NULL); /* Make sure the structure is valid */ \
265  assert(!is_empty_##struct_name(deq)); \
266  return deq->data[deq->front]; \
267  } \
268  \
269  type peek_back_##struct_name(struct_name* deq) { \
270  assert(deq != NULL); \
271  assert(deq->data != NULL); /* Make sure the structure is valid */ \
272  assert(!is_empty_##struct_name(deq)); \
273  return deq->data[(deq->back + deq->cap - 1) % deq->cap]; \
274  } \
275  \
276  void update_front_##struct_name(struct_name* deq, type element) { \
277  assert(deq != NULL); \
278  assert(deq->data != NULL); /* Make sure the structure is valid */ \
279  assert(!is_empty_##struct_name(deq)); \
280  deq->data[deq->front] = element; \
281  } \
282  \
283  void update_back_##struct_name(struct_name* deq, type element) { \
284  assert(deq != NULL); \
285  assert(deq->data != NULL); /* Make sure the structure is valid */ \
286  assert(!is_empty_##struct_name(deq)); \
287  deq->data[(deq->back + deq->cap - 1) % deq->cap] = element; \
288  } \
289  \
290  void update_and_destroy_front_##struct_name(struct_name* deq, \
291  type element) { \
292  assert(deq != NULL); \
293  assert(deq->data != NULL); /* Make sure the structure is valid */ \
294  assert(!is_empty_##struct_name(deq)); \
295  \
296  size_t idx = deq->front; \
297  \
298  if (deq->destructor != NULL) \
299  deq->destructor(deq->data[idx]); \
300  \
301  deq->data[idx] = element; \
302  } \
303  \
304  void update_and_destroy_back_##struct_name(struct_name* deq, \
305  type element) { \
306  assert(deq != NULL); \
307  assert(deq->data != NULL); /* Make sure the structure is valid */ \
308  assert(!is_empty_##struct_name(deq)); \
309  \
310  size_t idx = (deq->back + deq->cap - 1) % deq->cap; \
311  \
312  if (deq->destructor != NULL) \
313  deq->destructor(deq->data[idx]); \
314  \
315  deq->data[idx] = element; \
316  }
317 
318 #endif
void initialize_memory_pool(size_t size)
Allocate the memory pool.
Definition: memory_pool.c:83
void destroy_memory_pool()
Free all memory allocated in the memory pool.
Definition: memory_pool.c:143
Double ended queue generators specialized to any given type.
char * memory_pool_strdup(const char *str)
A version of strdup() that allocates the duplicate to the memory pool rather than with malloc directl...
Definition: memory_pool.c:148
void * memory_pool_alloc(size_t size)
Reserve some space in the memory pool and returns a unique address that can be written to and read fr...
Definition: memory_pool.c:98