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 
msgpack_zone_malloc_no_align(msgpack_zone * zone,size_t size)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 
msgpack_zone_malloc(msgpack_zone * zone,size_t size)106 static inline void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
107 {
108     char* aligned =
109         (char*)(
110             (size_t)(
111                 zone->chunk_list.ptr + (MSGPACK_ZONE_ALIGN - 1)
112             ) / MSGPACK_ZONE_ALIGN * MSGPACK_ZONE_ALIGN
113         );
114     size_t adjusted_size = size + (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) {
123             return (char*)((size_t)(ptr) / MSGPACK_ZONE_ALIGN * MSGPACK_ZONE_ALIGN);
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 
msgpack_zone_push_finalizer(msgpack_zone * zone,void (* func)(void * data),void * data)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 
msgpack_zone_swap(msgpack_zone * a,msgpack_zone * b)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 */
164