1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
/*
* CBOR for Ruby
*
* Copyright (C) 2013 Carsten Bormann
*
* Licensed under the Apache License, Version 2.0 (the "License").
*
* Based on:
***********/
/*
* MessagePack for Ruby
*
* Copyright (C) 2008-2013 Sadayuki Furuhashi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rmem.h"
void msgpack_rmem_init(msgpack_rmem_t* pm)
{
memset(pm, 0, sizeof(msgpack_rmem_t));
pm->head.pages = malloc(MSGPACK_RMEM_PAGE_SIZE * 32);
pm->head.mask = 0xffffffff; /* all bit is 1 = available */
}
void msgpack_rmem_destroy(msgpack_rmem_t* pm)
{
msgpack_rmem_chunk_t* c = pm->array_first;
msgpack_rmem_chunk_t* cend = pm->array_last;
for(; c != cend; c++) {
free(c->pages);
}
free(pm->head.pages);
free(pm->array_first);
}
void* _msgpack_rmem_alloc2(msgpack_rmem_t* pm)
{
msgpack_rmem_chunk_t* c = pm->array_first;
msgpack_rmem_chunk_t* last = pm->array_last;
for(; c != last; c++) {
if(_msgpack_rmem_chunk_available(c)) {
void* mem = _msgpack_rmem_chunk_alloc(c);
/* move to head */
msgpack_rmem_chunk_t tmp = pm->head;
pm->head = *c;
*c = tmp;
return mem;
}
}
if(c == pm->array_end) {
size_t capacity = c - pm->array_first;
size_t length = last - pm->array_first;
capacity = (capacity == 0) ? 8 : capacity * 2;
msgpack_rmem_chunk_t* array = realloc(pm->array_first, capacity * sizeof(msgpack_rmem_chunk_t));
pm->array_first = array;
pm->array_last = array + length;
pm->array_end = array + capacity;
}
/* allocate new chunk */
c = pm->array_last++;
/* move to head */
msgpack_rmem_chunk_t tmp = pm->head;
pm->head = *c;
*c = tmp;
pm->head.mask = 0xffffffff & (~1); /* "& (~1)" means first chunk is already allocated */
pm->head.pages = malloc(MSGPACK_RMEM_PAGE_SIZE * 32);
return pm->head.pages;
}
void _msgpack_rmem_chunk_free(msgpack_rmem_t* pm, msgpack_rmem_chunk_t* c)
{
if(pm->array_first->mask == 0xffffffff) {
/* free and move to last */
pm->array_last--;
free(c->pages);
*c = *pm->array_last;
return;
}
/* move to first */
msgpack_rmem_chunk_t tmp = *pm->array_first;
*pm->array_first = *c;
*c = tmp;
}
|