messagepack implementation for embedded systems (mbed / arduino)

Dependents:   hello_message_pack

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers zone.c Source File

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 }