Add treap remove method.
[svn-fe.git] / obj_pool.h
blob8cde327caa8e7101005b0bca80176102dc3740b8
1 /*
2 * Licensed under a two-clause BSD-style license.
3 * See LICENSE for details.
4 */
6 #ifndef OBJ_POOL_H_
7 #define OBJ_POOL_H_
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <unistd.h>
17 * The obj_pool_gen() macro generates a type-specific memory pool
18 * implementation.
20 * Arguments:
22 * pre : Prefix for generated functions (ex: string_).
23 * obj_t : Type for treap data structure (ex: char).
24 * intial_capacity : The initial size of the memory pool (ex: 4096).
27 #define obj_pool_gen(pre, obj_t, initial_capacity) \
28 static struct { \
29 uint32_t size; \
30 uint32_t capacity; \
31 obj_t *base; \
32 FILE *file; \
33 } pre##_pool = { 0, 0, NULL, NULL}; \
34 static void pre##_init(void) \
35 { \
36 struct stat st; \
37 size_t ps = sysconf (_SC_PAGESIZE); \
38 /* Touch binary file before opening read/write */ \
39 pre##_pool.file = fopen(#pre ".bin", "a"); \
40 fclose(pre##_pool.file); \
41 /* Open, check size, compute capacity */ \
42 pre##_pool.file = fopen(#pre ".bin", "r+"); \
43 fstat(fileno(pre##_pool.file), &st); \
44 pre##_pool.size = st.st_size / sizeof(obj_t); \
45 pre##_pool.capacity = ((st.st_size + ps - 1) & ~(ps - 1)) / sizeof(obj_t); \
46 if (pre##_pool.capacity < initial_capacity) \
47 pre##_pool.capacity = initial_capacity; \
48 /* Truncate to calculated capacity and map to VM */ \
49 ftruncate(fileno(pre##_pool.file), pre##_pool.capacity * sizeof(obj_t)); \
50 pre##_pool.base = mmap(0, pre##_pool.capacity * sizeof(obj_t), \
51 PROT_READ | PROT_WRITE, MAP_SHARED, \
52 fileno(pre##_pool.file), 0); \
53 } \
54 static uint32_t pre##_alloc(uint32_t count) \
55 { \
56 uint32_t offset; \
57 if (pre##_pool.size + count > pre##_pool.capacity) { \
58 if (NULL == pre##_pool.base) \
59 pre##_init(); \
60 fsync(fileno(pre##_pool.file)); \
61 munmap(pre##_pool.base, \
62 pre##_pool.capacity * sizeof(obj_t)); \
63 pre##_pool.base = NULL; \
64 while (pre##_pool.size + count > pre##_pool.capacity) \
65 if (pre##_pool.capacity) \
66 pre##_pool.capacity *= 2; \
67 else \
68 pre##_pool.capacity = initial_capacity; \
69 ftruncate(fileno(pre##_pool.file), \
70 pre##_pool.capacity * sizeof(obj_t)); \
71 pre##_pool.base = \
72 mmap(0, pre##_pool.capacity * sizeof(obj_t), \
73 PROT_READ | PROT_WRITE, MAP_SHARED, \
74 fileno(pre##_pool.file), 0); \
75 } \
76 offset = pre##_pool.size; \
77 pre##_pool.size += count; \
78 return offset; \
79 } \
80 static void pre##_free(uint32_t count) \
81 { \
82 pre##_pool.size -= count; \
83 } \
84 static uint32_t pre##_offset(obj_t *obj) \
85 { \
86 return obj == NULL ? ~0 : obj - pre##_pool.base; \
87 } \
88 static obj_t *pre##_pointer(uint32_t offset) \
89 { \
90 return offset >= pre##_pool.size ? NULL : &pre##_pool.base[offset]; \
91 } \
92 static void pre##_reset(void) \
93 { \
94 if (pre##_pool.base) { \
95 fsync(fileno(pre##_pool.file)); \
96 munmap(pre##_pool.base, \
97 pre##_pool.capacity * sizeof(obj_t)); \
98 ftruncate(fileno(pre##_pool.file), \
99 pre##_pool.size * sizeof(obj_t)); \
100 fclose(pre##_pool.file); \
102 pre##_pool.base = NULL; \
103 pre##_pool.size = 0; \
104 pre##_pool.capacity = 0; \
105 pre##_pool.file = NULL; \
108 #endif