messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
zone.c
00001 /* 00002 * MessagePack for C memory pool implementation 00003 * 00004 * Copyright (C) 2008-2009 FURUHASHI Sadayuki 00005 * 00006 * Distributed under the Boost Software License, Version 1.0. 00007 * (See accompanying file LICENSE_1_0.txt or copy at 00008 * http://www.boost.org/LICENSE_1_0.txt) 00009 */ 00010 #include "include/zone.h" 00011 #include <stdlib.h> 00012 #include <string.h> 00013 00014 struct msgpack_zone_chunk { 00015 struct msgpack_zone_chunk* next; 00016 /* data ... */ 00017 }; 00018 00019 static inline bool init_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size) 00020 { 00021 msgpack_zone_chunk* chunk = (msgpack_zone_chunk*)malloc( 00022 sizeof(msgpack_zone_chunk) + chunk_size); 00023 if(chunk == NULL) { 00024 return false; 00025 } 00026 00027 cl->head = chunk; 00028 cl->free = chunk_size; 00029 cl->ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk); 00030 chunk->next = NULL; 00031 00032 return true; 00033 } 00034 00035 static inline void destroy_chunk_list(msgpack_zone_chunk_list* cl) 00036 { 00037 msgpack_zone_chunk* c = cl->head; 00038 while(true) { 00039 msgpack_zone_chunk* n = c->next; 00040 free(c); 00041 if(n != NULL) { 00042 c = n; 00043 } else { 00044 break; 00045 } 00046 } 00047 } 00048 00049 static inline void clear_chunk_list(msgpack_zone_chunk_list* cl, size_t chunk_size) 00050 { 00051 msgpack_zone_chunk* c = cl->head; 00052 while(true) { 00053 msgpack_zone_chunk* n = c->next; 00054 if(n != NULL) { 00055 free(c); 00056 c = n; 00057 } else { 00058 cl->head = c; 00059 break; 00060 } 00061 } 00062 cl->head->next = NULL; 00063 cl->free = chunk_size; 00064 cl->ptr = ((char*)cl->head) + sizeof(msgpack_zone_chunk); 00065 } 00066 00067 void* msgpack_zone_malloc_expand(msgpack_zone* zone, size_t size) 00068 { 00069 msgpack_zone_chunk_list* const cl = &zone->chunk_list; 00070 msgpack_zone_chunk* chunk; 00071 00072 size_t sz = zone->chunk_size; 00073 00074 while(sz < size) { 00075 size_t tmp_sz = sz * 2; 00076 if (tmp_sz <= sz) { 00077 tmp_sz = size; 00078 break; 00079 } 00080 sz = tmp_sz; 00081 } 00082 00083 chunk = (msgpack_zone_chunk*)malloc( 00084 sizeof(msgpack_zone_chunk) + sz); 00085 if (chunk == NULL) { 00086 return NULL; 00087 } 00088 else { 00089 char* ptr = ((char*)chunk) + sizeof(msgpack_zone_chunk); 00090 chunk->next = cl->head; 00091 cl->head = chunk; 00092 cl->free = sz - size; 00093 cl->ptr = ptr + size; 00094 00095 return ptr; 00096 } 00097 } 00098 00099 00100 static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa) 00101 { 00102 fa->tail = NULL; 00103 fa->end = NULL; 00104 fa->array = NULL; 00105 } 00106 00107 static inline void call_finalizer_array(msgpack_zone_finalizer_array* fa) 00108 { 00109 msgpack_zone_finalizer* fin = fa->tail; 00110 for(; fin != fa->array; --fin) { 00111 (*(fin-1)->func)((fin-1)->data); 00112 } 00113 } 00114 00115 static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa) 00116 { 00117 call_finalizer_array(fa); 00118 free(fa->array); 00119 } 00120 00121 static inline void clear_finalizer_array(msgpack_zone_finalizer_array* fa) 00122 { 00123 call_finalizer_array(fa); 00124 fa->tail = fa->array; 00125 } 00126 00127 bool msgpack_zone_push_finalizer_expand(msgpack_zone* zone, 00128 void (*func)(void* data), void* data) 00129 { 00130 msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; 00131 msgpack_zone_finalizer* tmp; 00132 00133 const size_t nused = (size_t)(fa->end - fa->array); 00134 00135 size_t nnext; 00136 if(nused == 0) { 00137 nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ? 00138 72 / sizeof(msgpack_zone_finalizer) : 8; 00139 00140 } else { 00141 nnext = nused * 2; 00142 } 00143 00144 tmp = (msgpack_zone_finalizer*)realloc(fa->array, 00145 sizeof(msgpack_zone_finalizer) * nnext); 00146 if(tmp == NULL) { 00147 return false; 00148 } 00149 00150 fa->array = tmp; 00151 fa->end = tmp + nnext; 00152 fa->tail = tmp + nused; 00153 00154 fa->tail->func = func; 00155 fa->tail->data = data; 00156 00157 ++fa->tail; 00158 00159 return true; 00160 } 00161 00162 00163 bool msgpack_zone_is_empty(msgpack_zone* zone) 00164 { 00165 msgpack_zone_chunk_list* const cl = &zone->chunk_list; 00166 msgpack_zone_finalizer_array* const fa = &zone->finalizer_array; 00167 return cl->free == zone->chunk_size && cl->head->next == NULL && 00168 fa->tail == fa->array; 00169 } 00170 00171 00172 void msgpack_zone_destroy(msgpack_zone* zone) 00173 { 00174 destroy_finalizer_array(&zone->finalizer_array); 00175 destroy_chunk_list(&zone->chunk_list); 00176 } 00177 00178 void msgpack_zone_clear(msgpack_zone* zone) 00179 { 00180 clear_finalizer_array(&zone->finalizer_array); 00181 clear_chunk_list(&zone->chunk_list, zone->chunk_size); 00182 } 00183 00184 bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size) 00185 { 00186 zone->chunk_size = chunk_size; 00187 00188 if(!init_chunk_list(&zone->chunk_list, chunk_size)) { 00189 return false; 00190 } 00191 00192 init_finalizer_array(&zone->finalizer_array); 00193 00194 return true; 00195 } 00196 00197 msgpack_zone* msgpack_zone_new(size_t chunk_size) 00198 { 00199 msgpack_zone* zone = (msgpack_zone*)malloc( 00200 sizeof(msgpack_zone)); 00201 if(zone == NULL) { 00202 return NULL; 00203 } 00204 00205 zone->chunk_size = chunk_size; 00206 00207 if(!init_chunk_list(&zone->chunk_list, chunk_size)) { 00208 free(zone); 00209 return NULL; 00210 } 00211 00212 init_finalizer_array(&zone->finalizer_array); 00213 00214 return zone; 00215 } 00216 00217 void msgpack_zone_free(msgpack_zone* zone) 00218 { 00219 if(zone == NULL) { return; } 00220 msgpack_zone_destroy(zone); 00221 free(zone); 00222 }
Generated on Tue Jul 12 2022 22:51:46 by 1.7.2