1 /*
2 Copyright (C) 2015-2017 Alexander Borisov
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
18 Author: lex.borisov@gmail.com (Alexander Borisov)
19 */
20
21 #include "mycore/utils/mcobject.h"
22
mcobject_create(void)23 mcobject_t * mcobject_create(void)
24 {
25 return mycore_calloc(1, sizeof(mcobject_t));
26 }
27
mcobject_init(mcobject_t * mcobject,size_t chunk_size,size_t struct_size)28 mystatus_t mcobject_init(mcobject_t *mcobject, size_t chunk_size, size_t struct_size)
29 {
30 mcobject->struct_size = struct_size;
31 mcobject->chunk_size = chunk_size;
32
33 mcobject->chunk = NULL;
34
35 mcobject->cache_length = 0;
36 mcobject->cache_size = chunk_size;
37 mcobject->cache = (void**)mycore_malloc(sizeof(void*) * mcobject->cache_size);
38
39 if(mcobject->cache == NULL)
40 return MyCORE_STATUS_MCOBJECT_ERROR_CACHE_CREATE;
41
42 return MyCORE_STATUS_OK;
43 }
44
mcobject_clean(mcobject_t * mcobject)45 void mcobject_clean(mcobject_t *mcobject)
46 {
47 if(mcobject->chunk == NULL)
48 return;
49
50 mcobject_chunk_t* chunk = mcobject->chunk;
51
52 while(chunk->next)
53 chunk = chunk->next;
54
55 while(chunk) {
56 mcobject_chunk_t* tmp = chunk->prev;
57
58 if(chunk->begin) {
59 mycore_free(chunk->begin);
60 }
61
62 mycore_free(chunk);
63
64 chunk = tmp;
65 }
66
67 mcobject->chunk = NULL;
68 mcobject->cache_length = 0;
69 }
70
mcobject_destroy(mcobject_t * mcobject,bool destroy_self)71 mcobject_t * mcobject_destroy(mcobject_t *mcobject, bool destroy_self)
72 {
73 if(mcobject == NULL)
74 return NULL;
75
76 mcobject_clean(mcobject);
77
78 if(mcobject->cache) {
79 mycore_free(mcobject->cache);
80 mcobject->cache = NULL;
81 }
82
83 if(destroy_self) {
84 mycore_free(mcobject);
85 return NULL;
86 }
87
88 return mcobject;
89 }
90
mcobject_chunk_malloc(mcobject_t * mcobject,mystatus_t * status)91 void mcobject_chunk_malloc(mcobject_t* mcobject, mystatus_t* status)
92 {
93 if(status)
94 *status = MyCORE_STATUS_OK;
95
96 mcobject_chunk_t* chunk;
97
98 if(mcobject->chunk && mcobject->chunk->next) {
99 mcobject->chunk = mcobject->chunk->next;
100
101 mcobject->chunk->length = 0;
102
103 return;
104 }
105 else {
106 chunk = mycore_calloc(1, sizeof(mcobject_chunk_t));
107
108 if(chunk == NULL) {
109 if(status)
110 *status = MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_CREATE;
111
112 return;
113 }
114
115 chunk->begin = mycore_malloc(mcobject->struct_size * mcobject->chunk_size);
116
117 if(chunk->begin == NULL) {
118 if(status)
119 *status = MyCORE_STATUS_MCOBJECT_ERROR_CHUNK_INIT;
120
121 mycore_free(chunk);
122 return;
123 }
124
125 chunk->size = mcobject->chunk_size;
126 }
127
128 if(mcobject->chunk == NULL) {
129 mcobject->chunk = chunk;
130 return;
131 }
132
133 chunk->prev = mcobject->chunk;
134 mcobject->chunk->next = chunk;
135
136 mcobject->chunk = chunk;
137 }
138
mcobject_malloc(mcobject_t * mcobject,mystatus_t * status)139 void * mcobject_malloc(mcobject_t *mcobject, mystatus_t* status)
140 {
141 if(mcobject->cache_length) {
142 if(status)
143 *status = MyCORE_STATUS_OK;
144
145 mcobject->cache_length--;
146 return mcobject->cache[ mcobject->cache_length ];
147 }
148
149 mcobject_chunk_t* chunk = mcobject->chunk;
150
151 if(chunk == NULL || chunk->length >= chunk->size)
152 {
153 mystatus_t ns_status;
154 mcobject_chunk_malloc(mcobject, &ns_status);
155
156 if(ns_status) {
157 if(status)
158 *status = ns_status;
159
160 return NULL;
161 }
162
163 chunk = mcobject->chunk;
164 }
165
166 if(status)
167 *status = MyCORE_STATUS_OK;
168
169 chunk->length++;
170 return &chunk->begin[((chunk->length - 1) * mcobject->struct_size)];
171 }
172
mcobject_free(mcobject_t * mcobject,void * entry)173 mystatus_t mcobject_free(mcobject_t *mcobject, void *entry)
174 {
175 if(mcobject->cache_length >= mcobject->cache_size) {
176 size_t new_size = mcobject->cache_size << 1;
177
178 void **tmp = (void**)mycore_realloc(mcobject->cache, sizeof(void*) * new_size);
179
180 if(tmp) {
181 mcobject->cache = tmp;
182 mcobject->cache_size = new_size;
183 }
184 else
185 return MyCORE_STATUS_MCOBJECT_ERROR_CACHE_REALLOC;
186 }
187
188 mcobject->cache[ mcobject->cache_length ] = entry;
189 mcobject->cache_length++;
190
191 return MyCORE_STATUS_OK;
192 }
193
194
195