diff options
author | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 17:29:19 +1000 |
commit | 07274513e984f0b5544586c74508ccd16e7dcafa (patch) | |
tree | b32ff2a9136fbc1a4a6a0ed1e4d79cde0f5f16d9 /libraries/eina/src/lib/eina_share_common.c | |
parent | Added Irrlicht 1.8, but without all the Windows binaries. (diff) | |
download | SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.zip SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.gz SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.bz2 SledjHamr-07274513e984f0b5544586c74508ccd16e7dcafa.tar.xz |
Remove EFL, since it's been released now.
Diffstat (limited to 'libraries/eina/src/lib/eina_share_common.c')
-rw-r--r-- | libraries/eina/src/lib/eina_share_common.c | 949 |
1 files changed, 0 insertions, 949 deletions
diff --git a/libraries/eina/src/lib/eina_share_common.c b/libraries/eina/src/lib/eina_share_common.c deleted file mode 100644 index 776e429..0000000 --- a/libraries/eina/src/lib/eina_share_common.c +++ /dev/null | |||
@@ -1,949 +0,0 @@ | |||
1 | /* EINA - EFL data type library | ||
2 | * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010 | ||
3 | * Carsten Haitzler, | ||
4 | * Jorge Luis Zapata Muga, | ||
5 | * Cedric Bail, | ||
6 | * Gustavo Sverzut Barbieri | ||
7 | * Tom Hacohen | ||
8 | * Brett Nash | ||
9 | * | ||
10 | * This library is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU Lesser General Public | ||
12 | * License as published by the Free Software Foundation; either | ||
13 | * version 2.1 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | * This library is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * Lesser General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU Lesser General Public | ||
21 | * License along with this library; | ||
22 | * if not, see <http://www.gnu.org/licenses/>. | ||
23 | * | ||
24 | * This file incorporates work covered by the following copyright and | ||
25 | * permission notice: | ||
26 | * | ||
27 | * Copyright (C) 2008 Peter Wehrfritz | ||
28 | * | ||
29 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
30 | * of this software and associated documentation files (the "Software"), to | ||
31 | * deal in the Software without restriction, including without limitation the | ||
32 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
33 | * sell copies of the Software, and to permit persons to whom the Software is | ||
34 | * furnished to do so, subject to the following conditions: | ||
35 | * | ||
36 | * The above copyright notice and this permission notice shall be included in | ||
37 | * all copies of the Software and its Copyright notices. In addition publicly | ||
38 | * documented acknowledgment must be given that this software has been used if no | ||
39 | * source code of this software is made available publicly. This includes | ||
40 | * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing | ||
41 | * documents or any documentation provided with any product containing this | ||
42 | * software. This License does not apply to any software that links to the | ||
43 | * libraries provided by this software (statically or dynamically), but only to | ||
44 | * the software provided. | ||
45 | * | ||
46 | * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice | ||
47 | * and it's intent. | ||
48 | * | ||
49 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
50 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
51 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
52 | * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
53 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
54 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
55 | */ | ||
56 | |||
57 | #ifdef HAVE_CONFIG_H | ||
58 | # include "config.h" | ||
59 | #endif | ||
60 | |||
61 | #include <stdlib.h> | ||
62 | #include <stdio.h> | ||
63 | #include <string.h> | ||
64 | #include <stddef.h> | ||
65 | |||
66 | #ifdef EFL_HAVE_POSIX_THREADS | ||
67 | # include <pthread.h> | ||
68 | #endif | ||
69 | |||
70 | #ifdef HAVE_EVIL | ||
71 | # include <Evil.h> | ||
72 | #endif | ||
73 | |||
74 | #include "eina_config.h" | ||
75 | #include "eina_private.h" | ||
76 | #include "eina_hash.h" | ||
77 | #include "eina_rbtree.h" | ||
78 | #include "eina_error.h" | ||
79 | #include "eina_lock.h" | ||
80 | |||
81 | /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ | ||
82 | #include "eina_safety_checks.h" | ||
83 | #include "eina_share_common.h" | ||
84 | |||
85 | /*============================================================================* | ||
86 | * Local * | ||
87 | *============================================================================*/ | ||
88 | |||
89 | /** | ||
90 | * @cond LOCAL | ||
91 | */ | ||
92 | |||
93 | #define EINA_SHARE_COMMON_BUCKETS 256 | ||
94 | #define EINA_SHARE_COMMON_MASK 0xFF | ||
95 | |||
96 | static const char EINA_MAGIC_SHARE_STR[] = "Eina Share"; | ||
97 | static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head"; | ||
98 | |||
99 | static int _eina_share_common_count = 0; | ||
100 | |||
101 | #define EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(d, unlock, ...) \ | ||
102 | do { \ | ||
103 | if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_SHARE_HEAD)) \ | ||
104 | { \ | ||
105 | EINA_MAGIC_FAIL((d), EINA_MAGIC_SHARE_HEAD); \ | ||
106 | unlock; \ | ||
107 | return __VA_ARGS__; \ | ||
108 | } \ | ||
109 | } while (0) | ||
110 | |||
111 | #define EINA_MAGIC_CHECK_SHARE_COMMON_NODE(d, _node_magic, unlock) \ | ||
112 | do { \ | ||
113 | if (!EINA_MAGIC_CHECK((d), _node_magic)) \ | ||
114 | { \ | ||
115 | EINA_MAGIC_FAIL((d), _node_magic); \ | ||
116 | unlock; \ | ||
117 | } \ | ||
118 | } while (0) | ||
119 | |||
120 | #ifdef EINA_SHARE_USAGE | ||
121 | typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population; | ||
122 | #endif | ||
123 | |||
124 | typedef struct _Eina_Share_Common Eina_Share_Common; | ||
125 | typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node; | ||
126 | typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head; | ||
127 | |||
128 | struct _Eina_Share | ||
129 | { | ||
130 | Eina_Share_Common *share; | ||
131 | Eina_Magic node_magic; | ||
132 | #ifdef EINA_SHARE_COMMON_USAGE | ||
133 | Eina_Share_Common_Population population; | ||
134 | int max_node_population; | ||
135 | #endif | ||
136 | }; | ||
137 | |||
138 | struct _Eina_Share_Common | ||
139 | { | ||
140 | Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS]; | ||
141 | |||
142 | EINA_MAGIC | ||
143 | }; | ||
144 | |||
145 | struct _Eina_Share_Common_Node | ||
146 | { | ||
147 | Eina_Share_Common_Node *next; | ||
148 | |||
149 | EINA_MAGIC | ||
150 | |||
151 | unsigned int length; | ||
152 | unsigned int references; | ||
153 | char str[]; | ||
154 | }; | ||
155 | |||
156 | struct _Eina_Share_Common_Head | ||
157 | { | ||
158 | EINA_RBTREE; | ||
159 | EINA_MAGIC | ||
160 | |||
161 | int hash; | ||
162 | |||
163 | #ifdef EINA_SHARE_COMMON_USAGE | ||
164 | int population; | ||
165 | #endif | ||
166 | |||
167 | Eina_Share_Common_Node *head; | ||
168 | Eina_Share_Common_Node builtin_node; | ||
169 | }; | ||
170 | |||
171 | Eina_Bool _share_common_threads_activated = EINA_FALSE; | ||
172 | |||
173 | static Eina_Lock _mutex_big; | ||
174 | |||
175 | #ifdef EINA_SHARE_COMMON_USAGE | ||
176 | struct _Eina_Share_Common_Population | ||
177 | { | ||
178 | int count; | ||
179 | int max; | ||
180 | }; | ||
181 | |||
182 | static Eina_Share_Common_Population population = { 0, 0 }; | ||
183 | |||
184 | static Eina_Share_Common_Population population_group[4] = | ||
185 | { | ||
186 | { 0, 0 }, | ||
187 | { 0, 0 }, | ||
188 | { 0, 0 }, | ||
189 | { 0, 0 } | ||
190 | }; | ||
191 | |||
192 | static void | ||
193 | _eina_share_common_population_init(Eina_Share *share) | ||
194 | { | ||
195 | unsigned int i; | ||
196 | |||
197 | for (i = 0; | ||
198 | i < sizeof (share->population_group) / | ||
199 | sizeof (share->population_group[0]); | ||
200 | ++i) | ||
201 | { | ||
202 | share->population_group[i].count = 0; | ||
203 | share->population_group[i].max = 0; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void | ||
208 | _eina_share_common_population_shutdown(Eina_Share *share) | ||
209 | { | ||
210 | unsigned int i; | ||
211 | |||
212 | share->max_node_population = 0; | ||
213 | share->population.count = 0; | ||
214 | share->population.max = 0; | ||
215 | |||
216 | for (i = 0; | ||
217 | i < sizeof (share->population_group) / | ||
218 | sizeof (share->population_group[0]); | ||
219 | ++i) | ||
220 | { | ||
221 | share->population_group[i].count = 0; | ||
222 | share->population_group[i].max = 0; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | _eina_share_common_population_stats(Eina_Share *share) | ||
228 | { | ||
229 | unsigned int i; | ||
230 | |||
231 | fprintf(stderr, "eina share_common statistic:\n"); | ||
232 | fprintf(stderr, | ||
233 | " * maximum shared strings : %i\n", | ||
234 | share->population.max); | ||
235 | fprintf(stderr, | ||
236 | " * maximum shared strings per node : %i\n", | ||
237 | share->max_node_population); | ||
238 | |||
239 | for (i = 0; | ||
240 | i < sizeof (share->population_group) / | ||
241 | sizeof (share->population_group[0]); | ||
242 | ++i) | ||
243 | fprintf(stderr, | ||
244 | "DDD: %i strings of length %i, max strings: %i\n", | ||
245 | share->population_group[i].count, | ||
246 | i, | ||
247 | share->population_group[i].max); | ||
248 | } | ||
249 | |||
250 | void | ||
251 | eina_share_common_population_add(Eina_Share *share, int slen) | ||
252 | { | ||
253 | eina_lock_take(&_mutex_big); | ||
254 | |||
255 | share->population.count++; | ||
256 | if (share->population.count > share->population.max) | ||
257 | share->population.max = share->population.count; | ||
258 | |||
259 | if (slen < 4) | ||
260 | { | ||
261 | share->population_group[slen].count++; | ||
262 | if (share->population_group[slen].count > | ||
263 | share->population_group[slen].max) | ||
264 | share->population_group[slen].max = | ||
265 | share->population_group[slen].count; | ||
266 | } | ||
267 | |||
268 | eina_lock_release(&_mutex_big); | ||
269 | } | ||
270 | |||
271 | void | ||
272 | eina_share_common_population_del(Eina_Share *share, int slen) | ||
273 | { | ||
274 | eina_lock_take(&_mutex_big); | ||
275 | |||
276 | share->population.count--; | ||
277 | if (slen < 4) | ||
278 | share->population_group[slen].count--; | ||
279 | |||
280 | eina_lock_release(&_mutex_big); | ||
281 | } | ||
282 | |||
283 | static void | ||
284 | _eina_share_common_population_head_init(Eina_Share *share, | ||
285 | Eina_Share_Common_Head *head) | ||
286 | { | ||
287 | head->population = 1; | ||
288 | } | ||
289 | |||
290 | static void | ||
291 | _eina_share_common_population_head_add(Eina_Share *share, | ||
292 | Eina_Share_Common_Head *head) | ||
293 | { | ||
294 | head->population++; | ||
295 | if (head->population > share->max_node_population) | ||
296 | share->max_node_population = head->population; | ||
297 | } | ||
298 | |||
299 | static void | ||
300 | _eina_share_common_population_head_del(Eina_Share *share, | ||
301 | Eina_Share_Common_Head *head) | ||
302 | { | ||
303 | head->population--; | ||
304 | } | ||
305 | |||
306 | #else /* EINA_SHARE_COMMON_USAGE undefined */ | ||
307 | |||
308 | static void _eina_share_common_population_init(__UNUSED__ Eina_Share *share) { | ||
309 | } | ||
310 | static void _eina_share_common_population_shutdown(__UNUSED__ Eina_Share *share) | ||
311 | { | ||
312 | } | ||
313 | static void _eina_share_common_population_stats(__UNUSED__ Eina_Share *share) { | ||
314 | } | ||
315 | void eina_share_common_population_add(__UNUSED__ Eina_Share *share, | ||
316 | __UNUSED__ int slen) { | ||
317 | } | ||
318 | void eina_share_common_population_del(__UNUSED__ Eina_Share *share, | ||
319 | __UNUSED__ int slen) { | ||
320 | } | ||
321 | static void _eina_share_common_population_head_init( | ||
322 | __UNUSED__ Eina_Share *share, | ||
323 | __UNUSED__ Eina_Share_Common_Head *head) { | ||
324 | } | ||
325 | static void _eina_share_common_population_head_add( | ||
326 | __UNUSED__ Eina_Share *share, | ||
327 | __UNUSED__ | ||
328 | Eina_Share_Common_Head *head) { | ||
329 | } | ||
330 | static void _eina_share_common_population_head_del( | ||
331 | __UNUSED__ Eina_Share *share, | ||
332 | __UNUSED__ | ||
333 | Eina_Share_Common_Head *head) { | ||
334 | } | ||
335 | #endif | ||
336 | |||
337 | static int | ||
338 | _eina_share_common_cmp(const Eina_Share_Common_Head *ed, | ||
339 | const int *hash, | ||
340 | __UNUSED__ int length, | ||
341 | __UNUSED__ void *data) | ||
342 | { | ||
343 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0); | ||
344 | |||
345 | return ed->hash - *hash; | ||
346 | } | ||
347 | |||
348 | static Eina_Rbtree_Direction | ||
349 | _eina_share_common_node(const Eina_Share_Common_Head *left, | ||
350 | const Eina_Share_Common_Head *right, | ||
351 | __UNUSED__ void *data) | ||
352 | { | ||
353 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left, , 0); | ||
354 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0); | ||
355 | |||
356 | if (left->hash - right->hash < 0) | ||
357 | return EINA_RBTREE_LEFT; | ||
358 | |||
359 | return EINA_RBTREE_RIGHT; | ||
360 | } | ||
361 | |||
362 | static void | ||
363 | _eina_share_common_head_free(Eina_Share_Common_Head *ed, __UNUSED__ void *data) | ||
364 | { | ||
365 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, ); | ||
366 | |||
367 | while (ed->head) | ||
368 | { | ||
369 | Eina_Share_Common_Node *el = ed->head; | ||
370 | |||
371 | ed->head = ed->head->next; | ||
372 | if (el != &ed->builtin_node) | ||
373 | MAGIC_FREE(el); | ||
374 | } | ||
375 | MAGIC_FREE(ed); | ||
376 | } | ||
377 | |||
378 | static void | ||
379 | _eina_share_common_node_init(Eina_Share_Common_Node *node, | ||
380 | const char *str, | ||
381 | int slen, | ||
382 | unsigned int null_size, | ||
383 | Eina_Magic node_magic) | ||
384 | { | ||
385 | EINA_MAGIC_SET(node, node_magic); | ||
386 | node->references = 1; | ||
387 | node->length = slen; | ||
388 | memcpy(node->str, str, slen); | ||
389 | memset(node->str + slen, 0, null_size); /* Nullify the null */ | ||
390 | |||
391 | (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ | ||
392 | } | ||
393 | |||
394 | static Eina_Share_Common_Head * | ||
395 | _eina_share_common_head_alloc(int slen) | ||
396 | { | ||
397 | Eina_Share_Common_Head *head; | ||
398 | const size_t head_size = offsetof(Eina_Share_Common_Head, builtin_node.str); | ||
399 | |||
400 | head = malloc(head_size + slen); | ||
401 | if (!head) | ||
402 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
403 | |||
404 | return head; | ||
405 | } | ||
406 | |||
407 | static const char * | ||
408 | _eina_share_common_add_head(Eina_Share *share, | ||
409 | Eina_Share_Common_Head **p_bucket, | ||
410 | int hash, | ||
411 | const char *str, | ||
412 | unsigned int slen, | ||
413 | unsigned int null_size) | ||
414 | { | ||
415 | Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; | ||
416 | Eina_Share_Common_Head *head; | ||
417 | |||
418 | head = _eina_share_common_head_alloc(slen + null_size); | ||
419 | if (!head) | ||
420 | return NULL; | ||
421 | |||
422 | EINA_MAGIC_SET(head, EINA_MAGIC_SHARE_HEAD); | ||
423 | head->hash = hash; | ||
424 | head->head = &head->builtin_node; | ||
425 | _eina_share_common_node_init(head->head, | ||
426 | str, | ||
427 | slen, | ||
428 | null_size, | ||
429 | share->node_magic); | ||
430 | head->head->next = NULL; | ||
431 | |||
432 | _eina_share_common_population_head_init(share, head); | ||
433 | |||
434 | *p_tree = eina_rbtree_inline_insert | ||
435 | (*p_tree, EINA_RBTREE_GET(head), | ||
436 | EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); | ||
437 | |||
438 | return head->head->str; | ||
439 | } | ||
440 | |||
441 | static void | ||
442 | _eina_share_common_del_head(Eina_Share_Common_Head **p_bucket, | ||
443 | Eina_Share_Common_Head *head) | ||
444 | { | ||
445 | Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; | ||
446 | |||
447 | *p_tree = eina_rbtree_inline_remove | ||
448 | (*p_tree, EINA_RBTREE_GET(head), | ||
449 | EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); | ||
450 | |||
451 | MAGIC_FREE(head); | ||
452 | } | ||
453 | |||
454 | |||
455 | static inline Eina_Bool | ||
456 | _eina_share_common_node_eq(const Eina_Share_Common_Node *node, | ||
457 | const char *str, | ||
458 | unsigned int slen) | ||
459 | { | ||
460 | return ((node->length == slen) && | ||
461 | (memcmp(node->str, str, slen) == 0)); | ||
462 | } | ||
463 | |||
464 | static Eina_Share_Common_Node * | ||
465 | _eina_share_common_head_find(Eina_Share_Common_Head *head, | ||
466 | const char *str, | ||
467 | unsigned int slen) | ||
468 | { | ||
469 | Eina_Share_Common_Node *node, *prev; | ||
470 | |||
471 | node = head->head; | ||
472 | if (_eina_share_common_node_eq(node, str, slen)) | ||
473 | return node; | ||
474 | |||
475 | prev = node; | ||
476 | node = node->next; | ||
477 | for (; node; prev = node, node = node->next) | ||
478 | if (_eina_share_common_node_eq(node, str, slen)) | ||
479 | { | ||
480 | /* promote node, make hot items be at the beginning */ | ||
481 | prev->next = node->next; | ||
482 | node->next = head->head; | ||
483 | head->head = node; | ||
484 | return node; | ||
485 | } | ||
486 | |||
487 | return NULL; | ||
488 | } | ||
489 | |||
490 | static Eina_Bool | ||
491 | _eina_share_common_head_remove_node(Eina_Share_Common_Head *head, | ||
492 | const Eina_Share_Common_Node *node) | ||
493 | { | ||
494 | Eina_Share_Common_Node *cur, *prev; | ||
495 | |||
496 | if (head->head == node) | ||
497 | { | ||
498 | head->head = node->next; | ||
499 | return 1; | ||
500 | } | ||
501 | |||
502 | prev = head->head; | ||
503 | cur = head->head->next; | ||
504 | for (; cur; prev = cur, cur = cur->next) | ||
505 | if (cur == node) | ||
506 | { | ||
507 | prev->next = cur->next; | ||
508 | return 1; | ||
509 | } | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static Eina_Share_Common_Head * | ||
515 | _eina_share_common_find_hash(Eina_Share_Common_Head *bucket, int hash) | ||
516 | { | ||
517 | return (Eina_Share_Common_Head *)eina_rbtree_inline_lookup | ||
518 | (EINA_RBTREE_GET(bucket), &hash, 0, | ||
519 | EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL); | ||
520 | } | ||
521 | |||
522 | static Eina_Share_Common_Node * | ||
523 | _eina_share_common_node_alloc(unsigned int slen, unsigned int null_size) | ||
524 | { | ||
525 | Eina_Share_Common_Node *node; | ||
526 | const size_t node_size = offsetof(Eina_Share_Common_Node, str); | ||
527 | |||
528 | node = malloc(node_size + slen + null_size); | ||
529 | if (!node) | ||
530 | eina_error_set(EINA_ERROR_OUT_OF_MEMORY); | ||
531 | |||
532 | return node; | ||
533 | } | ||
534 | |||
535 | static Eina_Share_Common_Node * | ||
536 | _eina_share_common_node_from_str(const char *str, Eina_Magic node_magic) | ||
537 | { | ||
538 | Eina_Share_Common_Node *node; | ||
539 | const size_t offset = offsetof(Eina_Share_Common_Node, str); | ||
540 | |||
541 | node = (Eina_Share_Common_Node *)(str - offset); | ||
542 | EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node = NULL); | ||
543 | return node; | ||
544 | |||
545 | (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ | ||
546 | } | ||
547 | |||
548 | static Eina_Bool | ||
549 | eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, | ||
550 | Eina_Share_Common_Head *head, | ||
551 | struct dumpinfo *fdata) | ||
552 | { | ||
553 | Eina_Share_Common_Node *node; | ||
554 | |||
555 | fdata->used += sizeof(Eina_Share_Common_Head); | ||
556 | for (node = head->head; node; node = node->next) | ||
557 | { | ||
558 | printf("DDD: %5i %5i ", node->length, node->references); | ||
559 | printf("'%.*s'\n", node->length, ((char *)node) + sizeof(Eina_Share_Common_Node)); | ||
560 | fdata->used += sizeof(Eina_Share_Common_Node); | ||
561 | fdata->used += node->length; | ||
562 | fdata->saved += (node->references - 1) * node->length; | ||
563 | fdata->dups += node->references - 1; | ||
564 | fdata->unique++; | ||
565 | } | ||
566 | |||
567 | return EINA_TRUE; | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * @endcond | ||
572 | */ | ||
573 | |||
574 | |||
575 | /*============================================================================* | ||
576 | * Global * | ||
577 | *============================================================================*/ | ||
578 | |||
579 | /** | ||
580 | * @internal | ||
581 | * @brief Initialize the share_common module. | ||
582 | * | ||
583 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
584 | * | ||
585 | * This function sets up the share_common module of Eina. It is called by | ||
586 | * eina_init(). | ||
587 | * | ||
588 | * @see eina_init() | ||
589 | */ | ||
590 | Eina_Bool | ||
591 | eina_share_common_init(Eina_Share **_share, | ||
592 | Eina_Magic node_magic, | ||
593 | const char *node_magic_STR) | ||
594 | { | ||
595 | Eina_Share *share; | ||
596 | |||
597 | share = *_share = calloc(sizeof(Eina_Share), 1); | ||
598 | if (!share) goto on_error; | ||
599 | |||
600 | share->share = calloc(1, sizeof(Eina_Share_Common)); | ||
601 | if (!share->share) goto on_error; | ||
602 | |||
603 | share->node_magic = node_magic; | ||
604 | #define EMS(n) eina_magic_string_static_set(n, n ## _STR) | ||
605 | EMS(EINA_MAGIC_SHARE); | ||
606 | EMS(EINA_MAGIC_SHARE_HEAD); | ||
607 | EMS(node_magic); | ||
608 | #undef EMS | ||
609 | EINA_MAGIC_SET(share->share, EINA_MAGIC_SHARE); | ||
610 | |||
611 | _eina_share_common_population_init(share); | ||
612 | |||
613 | /* below is the common part among other all eina_share_common user */ | ||
614 | if (_eina_share_common_count++ != 0) | ||
615 | return EINA_TRUE; | ||
616 | |||
617 | eina_lock_new(&_mutex_big); | ||
618 | return EINA_TRUE; | ||
619 | |||
620 | on_error: | ||
621 | _eina_share_common_count--; | ||
622 | return EINA_FALSE; | ||
623 | } | ||
624 | |||
625 | /** | ||
626 | * @internal | ||
627 | * @brief Shut down the share_common module. | ||
628 | * | ||
629 | * @return #EINA_TRUE on success, #EINA_FALSE on failure. | ||
630 | * | ||
631 | * This function shuts down the share_common module set up by | ||
632 | * eina_share_common_init(). It is called by eina_shutdown(). | ||
633 | * | ||
634 | * @see eina_shutdown() | ||
635 | */ | ||
636 | Eina_Bool | ||
637 | eina_share_common_shutdown(Eina_Share **_share) | ||
638 | { | ||
639 | unsigned int i; | ||
640 | Eina_Share *share = *_share; | ||
641 | |||
642 | eina_lock_take(&_mutex_big); | ||
643 | |||
644 | _eina_share_common_population_stats(share); | ||
645 | |||
646 | /* remove any string still in the table */ | ||
647 | for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) | ||
648 | { | ||
649 | eina_rbtree_delete(EINA_RBTREE_GET( | ||
650 | share->share->buckets[i]), | ||
651 | EINA_RBTREE_FREE_CB( | ||
652 | _eina_share_common_head_free), NULL); | ||
653 | share->share->buckets[i] = NULL; | ||
654 | } | ||
655 | MAGIC_FREE(share->share); | ||
656 | |||
657 | _eina_share_common_population_shutdown(share); | ||
658 | |||
659 | eina_lock_release(&_mutex_big); | ||
660 | |||
661 | free(*_share); | ||
662 | *_share = NULL; | ||
663 | |||
664 | /* below is the common part among other all eina_share_common user */ | ||
665 | if (--_eina_share_common_count != 0) | ||
666 | return EINA_TRUE; | ||
667 | |||
668 | eina_lock_free(&_mutex_big); | ||
669 | |||
670 | return EINA_TRUE; | ||
671 | } | ||
672 | |||
673 | #ifdef EFL_HAVE_THREADS | ||
674 | |||
675 | /** | ||
676 | * @internal | ||
677 | * @brief Activate the share_common mutexes. | ||
678 | * | ||
679 | * This function activate the mutexes in the eina share_common module. It is called by | ||
680 | * eina_threads_init(). | ||
681 | * | ||
682 | * @see eina_threads_init() | ||
683 | */ | ||
684 | void | ||
685 | eina_share_common_threads_init(void) | ||
686 | { | ||
687 | _share_common_threads_activated = EINA_TRUE; | ||
688 | } | ||
689 | |||
690 | /** | ||
691 | * @internal | ||
692 | * @brief Shut down the share_common mutexes. | ||
693 | * | ||
694 | * This function shuts down the mutexes in the share_common module. | ||
695 | * It is called by eina_threads_shutdown(). | ||
696 | * | ||
697 | * @see eina_threads_shutdown() | ||
698 | */ | ||
699 | void | ||
700 | eina_share_common_threads_shutdown(void) | ||
701 | { | ||
702 | _share_common_threads_activated = EINA_FALSE; | ||
703 | } | ||
704 | |||
705 | #endif | ||
706 | |||
707 | /*============================================================================* | ||
708 | * API * | ||
709 | *============================================================================*/ | ||
710 | |||
711 | /** | ||
712 | * @cond LOCAL | ||
713 | */ | ||
714 | |||
715 | const char * | ||
716 | eina_share_common_add_length(Eina_Share *share, | ||
717 | const char *str, | ||
718 | unsigned int slen, | ||
719 | unsigned int null_size) | ||
720 | { | ||
721 | Eina_Share_Common_Head **p_bucket, *ed; | ||
722 | Eina_Share_Common_Node *el; | ||
723 | int hash_num, hash; | ||
724 | |||
725 | if (!str) | ||
726 | return NULL; | ||
727 | |||
728 | eina_share_common_population_add(share, slen); | ||
729 | |||
730 | if (slen <= 0) | ||
731 | return NULL; | ||
732 | |||
733 | hash = eina_hash_superfast(str, slen); | ||
734 | hash_num = hash & 0xFF; | ||
735 | hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; | ||
736 | |||
737 | eina_lock_take(&_mutex_big); | ||
738 | p_bucket = share->share->buckets + hash_num; | ||
739 | |||
740 | ed = _eina_share_common_find_hash(*p_bucket, hash); | ||
741 | if (!ed) | ||
742 | { | ||
743 | const char *s = _eina_share_common_add_head(share, | ||
744 | p_bucket, | ||
745 | hash, | ||
746 | str, | ||
747 | slen, | ||
748 | null_size); | ||
749 | eina_lock_release(&_mutex_big); | ||
750 | return s; | ||
751 | } | ||
752 | |||
753 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), NULL); | ||
754 | |||
755 | el = _eina_share_common_head_find(ed, str, slen); | ||
756 | if (el) | ||
757 | { | ||
758 | EINA_MAGIC_CHECK_SHARE_COMMON_NODE(el, | ||
759 | share->node_magic, | ||
760 | eina_lock_release(&_mutex_big)); | ||
761 | el->references++; | ||
762 | eina_lock_release(&_mutex_big); | ||
763 | return el->str; | ||
764 | } | ||
765 | |||
766 | el = _eina_share_common_node_alloc(slen, null_size); | ||
767 | if (!el) | ||
768 | { | ||
769 | eina_lock_release(&_mutex_big); | ||
770 | return NULL; | ||
771 | } | ||
772 | |||
773 | _eina_share_common_node_init(el, str, slen, null_size, share->node_magic); | ||
774 | el->next = ed->head; | ||
775 | ed->head = el; | ||
776 | _eina_share_common_population_head_add(share, ed); | ||
777 | |||
778 | eina_lock_release(&_mutex_big); | ||
779 | |||
780 | return el->str; | ||
781 | } | ||
782 | |||
783 | const char * | ||
784 | eina_share_common_ref(Eina_Share *share, const char *str) | ||
785 | { | ||
786 | Eina_Share_Common_Node *node; | ||
787 | |||
788 | if (!str) | ||
789 | return NULL; | ||
790 | |||
791 | eina_lock_take(&_mutex_big); | ||
792 | node = _eina_share_common_node_from_str(str, share->node_magic); | ||
793 | if (!node) | ||
794 | { | ||
795 | eina_lock_release(&_mutex_big); | ||
796 | return str; | ||
797 | } | ||
798 | node->references++; | ||
799 | |||
800 | eina_lock_release(&_mutex_big); | ||
801 | |||
802 | eina_share_common_population_add(share, node->length); | ||
803 | |||
804 | return str; | ||
805 | } | ||
806 | |||
807 | |||
808 | Eina_Bool | ||
809 | eina_share_common_del(Eina_Share *share, const char *str) | ||
810 | { | ||
811 | unsigned int slen; | ||
812 | Eina_Share_Common_Head *ed; | ||
813 | Eina_Share_Common_Head **p_bucket; | ||
814 | Eina_Share_Common_Node *node; | ||
815 | int hash_num, hash; | ||
816 | |||
817 | if (!str) | ||
818 | return EINA_TRUE; | ||
819 | |||
820 | eina_lock_take(&_mutex_big); | ||
821 | |||
822 | node = _eina_share_common_node_from_str(str, share->node_magic); | ||
823 | if (!node) | ||
824 | goto on_error; | ||
825 | |||
826 | slen = node->length; | ||
827 | eina_share_common_population_del(share, slen); | ||
828 | if (node->references > 1) | ||
829 | { | ||
830 | node->references--; | ||
831 | eina_lock_release(&_mutex_big); | ||
832 | return EINA_TRUE; | ||
833 | } | ||
834 | |||
835 | node->references = 0; | ||
836 | |||
837 | hash = eina_hash_superfast(str, slen); | ||
838 | hash_num = hash & 0xFF; | ||
839 | hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; | ||
840 | |||
841 | p_bucket = share->share->buckets + hash_num; | ||
842 | ed = _eina_share_common_find_hash(*p_bucket, hash); | ||
843 | if (!ed) | ||
844 | goto on_error; | ||
845 | |||
846 | EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), EINA_FALSE); | ||
847 | |||
848 | if (!_eina_share_common_head_remove_node(ed, node)) | ||
849 | goto on_error; | ||
850 | |||
851 | if (node != &ed->builtin_node) | ||
852 | MAGIC_FREE(node); | ||
853 | |||
854 | if (!ed->head) | ||
855 | _eina_share_common_del_head(p_bucket, ed); | ||
856 | else | ||
857 | _eina_share_common_population_head_del(share, ed); | ||
858 | |||
859 | eina_lock_release(&_mutex_big); | ||
860 | |||
861 | return EINA_TRUE; | ||
862 | |||
863 | on_error: | ||
864 | eina_lock_release(&_mutex_big); | ||
865 | /* possible segfault happened before here, but... */ | ||
866 | return EINA_FALSE; | ||
867 | } | ||
868 | |||
869 | int | ||
870 | eina_share_common_length(__UNUSED__ Eina_Share *share, const char *str) | ||
871 | { | ||
872 | const Eina_Share_Common_Node *node; | ||
873 | |||
874 | if (!str) | ||
875 | return -1; | ||
876 | |||
877 | node = _eina_share_common_node_from_str(str, share->node_magic); | ||
878 | if (!node) return 0; | ||
879 | return node->length; | ||
880 | } | ||
881 | |||
882 | void | ||
883 | eina_share_common_dump(Eina_Share *share, void (*additional_dump)( | ||
884 | struct dumpinfo *), int used) | ||
885 | { | ||
886 | Eina_Iterator *it; | ||
887 | unsigned int i; | ||
888 | struct dumpinfo di; | ||
889 | |||
890 | if (!share) | ||
891 | return; | ||
892 | |||
893 | di.used = used; | ||
894 | di.saved = 0; | ||
895 | di.dups = 0; | ||
896 | di.unique = 0; | ||
897 | printf("DDD: len ref string\n"); | ||
898 | printf("DDD:-------------------\n"); | ||
899 | |||
900 | eina_lock_take(&_mutex_big); | ||
901 | for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) | ||
902 | { | ||
903 | if (!share->share->buckets[i]) | ||
904 | { | ||
905 | continue; // printf("DDD: BUCKET # %i (HEAD=%i, NODE=%i)\n", i, | ||
906 | |||
907 | } | ||
908 | |||
909 | // sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node)); | ||
910 | it = eina_rbtree_iterator_prefix( | ||
911 | (Eina_Rbtree *)share->share->buckets[i]); | ||
912 | eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di); | ||
913 | eina_iterator_free(it); | ||
914 | } | ||
915 | if (additional_dump) | ||
916 | additional_dump(&di); | ||
917 | |||
918 | #ifdef EINA_SHARE_COMMON_USAGE | ||
919 | /* One character strings are not counted in the hash. */ | ||
920 | di.saved += share->population_group[0].count * sizeof(char); | ||
921 | di.saved += share->population_group[1].count * sizeof(char) * 2; | ||
922 | #endif | ||
923 | printf("DDD:-------------------\n"); | ||
924 | printf("DDD: usage (bytes) = %i, saved = %i (%3.0f%%)\n", | ||
925 | di.used, di.saved, di.used ? (di.saved * 100.0 / di.used) : 0.0); | ||
926 | printf("DDD: unique: %d, duplicates: %d (%3.0f%%)\n", | ||
927 | di.unique, di.dups, di.unique ? (di.dups * 100.0 / di.unique) : 0.0); | ||
928 | |||
929 | #ifdef EINA_SHARE_COMMON_USAGE | ||
930 | printf("DDD: Allocated strings: %i\n", share->population.count); | ||
931 | printf("DDD: Max allocated strings: %i\n", share->population.max); | ||
932 | |||
933 | for (i = 0; | ||
934 | i < sizeof (share->population_group) / | ||
935 | sizeof (share->population_group[0]); | ||
936 | ++i) | ||
937 | fprintf(stderr, | ||
938 | "DDD: %i strings of length %i, max strings: %i\n", | ||
939 | share->population_group[i].count, | ||
940 | i, | ||
941 | share->population_group[i].max); | ||
942 | #endif | ||
943 | |||
944 | eina_lock_release(&_mutex_big); | ||
945 | } | ||
946 | |||
947 | /** | ||
948 | * @endcond | ||
949 | */ | ||