Commit | Line | Data |
---|---|---|
116a02e3 JG |
1 | /* |
2 | * MessagePack for C memory pool implementation | |
3 | * | |
4 | * Copyright (C) 2008-2010 FURUHASHI Sadayuki | |
5 | * | |
6 | * Distributed under the Boost Software License, Version 1.0. | |
7 | * (See accompanying file LICENSE_1_0.txt or copy at | |
8 | * http://www.boost.org/LICENSE_1_0.txt) | |
9 | */ | |
10 | #ifndef MSGPACK_ZONE_H | |
11 | #define MSGPACK_ZONE_H | |
12 | ||
13 | #include "sysdep.h" | |
14 | ||
15 | #ifdef __cplusplus | |
16 | extern "C" { | |
17 | #endif | |
18 | ||
19 | ||
20 | /** | |
21 | * @defgroup msgpack_zone Memory zone | |
22 | * @ingroup msgpack | |
23 | * @{ | |
24 | */ | |
25 | ||
26 | typedef struct msgpack_zone_finalizer { | |
27 | void (*func)(void* data); | |
28 | void* data; | |
29 | } msgpack_zone_finalizer; | |
30 | ||
31 | typedef struct msgpack_zone_finalizer_array { | |
32 | msgpack_zone_finalizer* tail; | |
33 | msgpack_zone_finalizer* end; | |
34 | msgpack_zone_finalizer* array; | |
35 | } msgpack_zone_finalizer_array; | |
36 | ||
37 | struct msgpack_zone_chunk; | |
38 | typedef struct msgpack_zone_chunk msgpack_zone_chunk; | |
39 | ||
40 | typedef struct msgpack_zone_chunk_list { | |
41 | size_t free; | |
42 | char* ptr; | |
43 | msgpack_zone_chunk* head; | |
44 | } msgpack_zone_chunk_list; | |
45 | ||
46 | typedef struct msgpack_zone { | |
47 | msgpack_zone_chunk_list chunk_list; | |
48 | msgpack_zone_finalizer_array finalizer_array; | |
49 | size_t chunk_size; | |
50 | } msgpack_zone; | |
51 | ||
52 | #ifndef MSGPACK_ZONE_CHUNK_SIZE | |
53 | #define MSGPACK_ZONE_CHUNK_SIZE 8192 | |
54 | #endif | |
55 | ||
56 | MSGPACK_DLLEXPORT | |
57 | bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size); | |
58 | MSGPACK_DLLEXPORT | |
59 | void msgpack_zone_destroy(msgpack_zone* zone); | |
60 | ||
61 | MSGPACK_DLLEXPORT | |
62 | msgpack_zone* msgpack_zone_new(size_t chunk_size); | |
63 | MSGPACK_DLLEXPORT | |
64 | void msgpack_zone_free(msgpack_zone* zone); | |
65 | ||
66 | static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size); | |
67 | static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size); | |
68 | ||
69 | static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone, | |
70 | void (*func)(void* data), void* data); | |
71 | ||
72 | static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b); | |
73 | ||
74 | MSGPACK_DLLEXPORT | |
75 | bool msgpack_zone_is_empty(msgpack_zone* zone); | |
76 | ||
77 | MSGPACK_DLLEXPORT | |
78 | void msgpack_zone_clear(msgpack_zone* zone); | |
79 | ||
80 | /** @} */ | |
81 | ||
82 | ||
83 | #ifndef MSGPACK_ZONE_ALIGN | |
84 | #define MSGPACK_ZONE_ALIGN sizeof(void*) | |
85 | #endif | |
86 | ||
87 | MSGPACK_DLLEXPORT | |
88 | void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size); | |
89 | ||
90 | static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size) | |
91 | { | |
92 | char* ptr; | |
93 | msgpack_zone_chunk_list* cl = &zone->chunk_list; | |
94 | ||
95 | if(zone->chunk_list.free < size) { | |
96 | return msgpack_zone_malloc_expand(zone, size); | |
97 | } | |
98 | ||
99 | ptr = cl->ptr; | |
100 | cl->free -= size; | |
101 | cl->ptr += size; | |
102 | ||
103 | return ptr; | |
104 | } | |
105 | ||
106 | static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size) | |
107 | { | |
108 | char* aligned = | |
109 | (char*)( | |
0c07860d | 110 | (uintptr_t)( |
116a02e3 | 111 | zone->chunk_list.ptr + (MSGPACK_ZONE_ALIGN - 1) |
0c07860d | 112 | ) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1) |
116a02e3 JG |
113 | ); |
114 | size_t adjusted_size = size + (size_t)(aligned - zone->chunk_list.ptr); | |
115 | if(zone->chunk_list.free >= adjusted_size) { | |
116 | zone->chunk_list.free -= adjusted_size; | |
117 | zone->chunk_list.ptr += adjusted_size; | |
118 | return aligned; | |
119 | } | |
120 | { | |
121 | void* ptr = msgpack_zone_malloc_expand(zone, size + (MSGPACK_ZONE_ALIGN - 1)); | |
122 | if (ptr) { | |
0c07860d | 123 | return (char*)((uintptr_t)(ptr) & ~(uintptr_t)(MSGPACK_ZONE_ALIGN - 1)); |
116a02e3 JG |
124 | } |
125 | } | |
126 | return NULL; | |
127 | } | |
128 | ||
129 | ||
130 | bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone, | |
131 | void (*func)(void* data), void* data); | |
132 | ||
133 | static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone, | |
134 | void (*func)(void* data), void* data) | |
135 | { | |
136 | msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; | |
137 | msgpack_zone_finalizer* fin = fa->tail; | |
138 | ||
139 | if(fin == fa->end) { | |
140 | return msgpack_zone_push_finalizer_expand(zone, func, data); | |
141 | } | |
142 | ||
143 | fin->func = func; | |
144 | fin->data = data; | |
145 | ||
146 | ++fa->tail; | |
147 | ||
148 | return true; | |
149 | } | |
150 | ||
151 | static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b) | |
152 | { | |
153 | msgpack_zone tmp = *a; | |
154 | *a = *b; | |
155 | *b = tmp; | |
156 | } | |
157 | ||
158 | ||
159 | #ifdef __cplusplus | |
160 | } | |
161 | #endif | |
162 | ||
163 | #endif /* msgpack/zone.h */ |