From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- libraries/eina/src/lib/eina_share_common.c | 977 +++++++++++++++++++++++++++++ 1 file changed, 977 insertions(+) create mode 100644 libraries/eina/src/lib/eina_share_common.c (limited to 'libraries/eina/src/lib/eina_share_common.c') diff --git a/libraries/eina/src/lib/eina_share_common.c b/libraries/eina/src/lib/eina_share_common.c new file mode 100644 index 0000000..90e1868 --- /dev/null +++ b/libraries/eina/src/lib/eina_share_common.c @@ -0,0 +1,977 @@ +/* EINA - EFL data type library + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2010 + * Carsten Haitzler, + * Jorge Luis Zapata Muga, + * Cedric Bail, + * Gustavo Sverzut Barbieri + * Tom Hacohen + * Brett Nash + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright (C) 2008 Peter Wehrfritz + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies of the Software and its Copyright notices. In addition publicly + * documented acknowledgment must be given that this software has been used if no + * source code of this software is made available publicly. This includes + * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing + * documents or any documentation provided with any product containing this + * software. This License does not apply to any software that links to the + * libraries provided by this software (statically or dynamically), but only to + * the software provided. + * + * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice + * and it's intent. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#ifdef EFL_HAVE_POSIX_THREADS +# include +#endif + +#ifdef HAVE_EVIL +# include +#endif + +#include "eina_config.h" +#include "eina_private.h" +#include "eina_hash.h" +#include "eina_rbtree.h" +#include "eina_error.h" +#include "eina_log.h" +#include "eina_lock.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" +#include "eina_share_common.h" + +/*============================================================================* +* Local * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +#define EINA_SHARE_COMMON_BUCKETS 256 +#define EINA_SHARE_COMMON_MASK 0xFF + +static const char EINA_MAGIC_SHARE_STR[] = "Eina Share"; +static const char EINA_MAGIC_SHARE_HEAD_STR[] = "Eina Share Head"; + +static int _eina_share_common_count = 0; + +#define EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(d, unlock, ...) \ + do { \ + if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_SHARE_HEAD)) \ + { \ + EINA_MAGIC_FAIL((d), EINA_MAGIC_SHARE_HEAD); \ + unlock; \ + return __VA_ARGS__; \ + } \ + } while (0) + +#define EINA_MAGIC_CHECK_SHARE_COMMON_NODE(d, _node_magic, unlock) \ + do { \ + if (!EINA_MAGIC_CHECK((d), _node_magic)) \ + { \ + EINA_MAGIC_FAIL((d), _node_magic); \ + unlock; \ + } \ + } while (0) + +#ifdef EINA_SHARE_USAGE +typedef struct _Eina_Share_Common_Population Eina_Share_Common_Population; +#endif + +typedef struct _Eina_Share_Common Eina_Share_Common; +typedef struct _Eina_Share_Common_Node Eina_Share_Common_Node; +typedef struct _Eina_Share_Common_Head Eina_Share_Common_Head; + +int _eina_share_common_log_dom = -1; + +struct _Eina_Share +{ + Eina_Share_Common *share; + Eina_Magic node_magic; +#ifdef EINA_SHARE_COMMON_USAGE + Eina_Share_Common_Population population; + int max_node_population; +#endif +}; + +struct _Eina_Share_Common +{ + Eina_Share_Common_Head *buckets[EINA_SHARE_COMMON_BUCKETS]; + + EINA_MAGIC +}; + +struct _Eina_Share_Common_Node +{ + Eina_Share_Common_Node *next; + + EINA_MAGIC + + unsigned int length; + unsigned int references; + char str[]; +}; + +struct _Eina_Share_Common_Head +{ + EINA_RBTREE; + EINA_MAGIC + + int hash; + +#ifdef EINA_SHARE_COMMON_USAGE + int population; +#endif + + Eina_Share_Common_Node *head; + Eina_Share_Common_Node builtin_node; +}; + +Eina_Bool _share_common_threads_activated = EINA_FALSE; + +static Eina_Lock _mutex_big; + +#ifdef EINA_SHARE_COMMON_USAGE +struct _Eina_Share_Common_Population +{ + int count; + int max; +}; + +static Eina_Share_Common_Population population = { 0, 0 }; + +static Eina_Share_Common_Population population_group[4] = +{ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 } +}; + +static void +_eina_share_common_population_init(Eina_Share *share) +{ + unsigned int i; + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + { + share->population_group[i].count = 0; + share->population_group[i].max = 0; + } +} + +static void +_eina_share_common_population_shutdown(Eina_Share *share) +{ + unsigned int i; + + share->max_node_population = 0; + share->population.count = 0; + share->population.max = 0; + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + { + share->population_group[i].count = 0; + share->population_group[i].max = 0; + } +} + +static void +_eina_share_common_population_stats(Eina_Share *share) +{ + unsigned int i; + + fprintf(stderr, "eina share_common statistic:\n"); + fprintf(stderr, + " * maximum shared strings : %i\n", + share->population.max); + fprintf(stderr, + " * maximum shared strings per node : %i\n", + share->max_node_population); + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + fprintf(stderr, + "DDD: %i strings of length %i, max strings: %i\n", + share->population_group[i].count, + i, + share->population_group[i].max); +} + +void +eina_share_common_population_add(Eina_Share *share, int slen) +{ + eina_lock_take(&_mutex_big); + + share->population.count++; + if (share->population.count > share->population.max) + share->population.max = share->population.count; + + if (slen < 4) + { + share->population_group[slen].count++; + if (share->population_group[slen].count > + share->population_group[slen].max) + share->population_group[slen].max = + share->population_group[slen].count; + } + + eina_lock_release(&_mutex_big); +} + +void +eina_share_common_population_del(Eina_Share *share, int slen) +{ + eina_lock_take(&_mutex_big); + + share->population.count--; + if (slen < 4) + share->population_group[slen].count--; + + eina_lock_release(&_mutex_big); +} + +static void +_eina_share_common_population_head_init(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population = 1; +} + +static void +_eina_share_common_population_head_add(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population++; + if (head->population > share->max_node_population) + share->max_node_population = head->population; +} + +static void +_eina_share_common_population_head_del(Eina_Share *share, + Eina_Share_Common_Head *head) +{ + head->population--; +} + +#else /* EINA_SHARE_COMMON_USAGE undefined */ + +static void _eina_share_common_population_init(__UNUSED__ Eina_Share *share) { +} +static void _eina_share_common_population_shutdown(__UNUSED__ Eina_Share *share) +{ +} +static void _eina_share_common_population_stats(__UNUSED__ Eina_Share *share) { +} +void eina_share_common_population_add(__UNUSED__ Eina_Share *share, + __UNUSED__ int slen) { +} +void eina_share_common_population_del(__UNUSED__ Eina_Share *share, + __UNUSED__ int slen) { +} +static void _eina_share_common_population_head_init( + __UNUSED__ Eina_Share *share, + __UNUSED__ Eina_Share_Common_Head *head) { +} +static void _eina_share_common_population_head_add( + __UNUSED__ Eina_Share *share, + __UNUSED__ + Eina_Share_Common_Head *head) { +} +static void _eina_share_common_population_head_del( + __UNUSED__ Eina_Share *share, + __UNUSED__ + Eina_Share_Common_Head *head) { +} +#endif + +static int +_eina_share_common_cmp(const Eina_Share_Common_Head *ed, + const int *hash, + __UNUSED__ int length, + __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, , 0); + + return ed->hash - *hash; +} + +static Eina_Rbtree_Direction +_eina_share_common_node(const Eina_Share_Common_Head *left, + const Eina_Share_Common_Head *right, + __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(left, , 0); + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(right, , 0); + + if (left->hash - right->hash < 0) + return EINA_RBTREE_LEFT; + + return EINA_RBTREE_RIGHT; +} + +static void +_eina_share_common_head_free(Eina_Share_Common_Head *ed, __UNUSED__ void *data) +{ + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, ); + + while (ed->head) + { + Eina_Share_Common_Node *el = ed->head; + + ed->head = ed->head->next; + if (el != &ed->builtin_node) + MAGIC_FREE(el); + } + MAGIC_FREE(ed); +} + +static void +_eina_share_common_node_init(Eina_Share_Common_Node *node, + const char *str, + int slen, + unsigned int null_size, + Eina_Magic node_magic) +{ + EINA_MAGIC_SET(node, node_magic); + node->references = 1; + node->length = slen; + memcpy(node->str, str, slen); + memset(node->str + slen, 0, null_size); /* Nullify the null */ + + (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ +} + +static Eina_Share_Common_Head * +_eina_share_common_head_alloc(int slen) +{ + Eina_Share_Common_Head *head; + const size_t head_size = offsetof(Eina_Share_Common_Head, builtin_node.str); + + head = malloc(head_size + slen); + if (!head) + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + + return head; +} + +static const char * +_eina_share_common_add_head(Eina_Share *share, + Eina_Share_Common_Head **p_bucket, + int hash, + const char *str, + unsigned int slen, + unsigned int null_size) +{ + Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; + Eina_Share_Common_Head *head; + + head = _eina_share_common_head_alloc(slen + null_size); + if (!head) + return NULL; + + EINA_MAGIC_SET(head, EINA_MAGIC_SHARE_HEAD); + head->hash = hash; + head->head = &head->builtin_node; + _eina_share_common_node_init(head->head, + str, + slen, + null_size, + share->node_magic); + head->head->next = NULL; + + _eina_share_common_population_head_init(share, head); + + *p_tree = eina_rbtree_inline_insert + (*p_tree, EINA_RBTREE_GET(head), + EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); + + return head->head->str; +} + +static void +_eina_share_common_del_head(Eina_Share_Common_Head **p_bucket, + Eina_Share_Common_Head *head) +{ + Eina_Rbtree **p_tree = (Eina_Rbtree **)p_bucket; + + *p_tree = eina_rbtree_inline_remove + (*p_tree, EINA_RBTREE_GET(head), + EINA_RBTREE_CMP_NODE_CB(_eina_share_common_node), NULL); + + MAGIC_FREE(head); +} + + +static inline Eina_Bool +_eina_share_common_node_eq(const Eina_Share_Common_Node *node, + const char *str, + unsigned int slen) +{ + return ((node->length == slen) && + (memcmp(node->str, str, slen) == 0)); +} + +static Eina_Share_Common_Node * +_eina_share_common_head_find(Eina_Share_Common_Head *head, + const char *str, + unsigned int slen) +{ + Eina_Share_Common_Node *node, *prev; + + node = head->head; + if (_eina_share_common_node_eq(node, str, slen)) + return node; + + prev = node; + node = node->next; + for (; node; prev = node, node = node->next) + if (_eina_share_common_node_eq(node, str, slen)) + { + /* promote node, make hot items be at the beginning */ + prev->next = node->next; + node->next = head->head; + head->head = node; + return node; + } + + return NULL; +} + +static Eina_Bool +_eina_share_common_head_remove_node(Eina_Share_Common_Head *head, + const Eina_Share_Common_Node *node) +{ + Eina_Share_Common_Node *cur, *prev; + + if (head->head == node) + { + head->head = node->next; + return 1; + } + + prev = head->head; + cur = head->head->next; + for (; cur; prev = cur, cur = cur->next) + if (cur == node) + { + prev->next = cur->next; + return 1; + } + + return 0; +} + +static Eina_Share_Common_Head * +_eina_share_common_find_hash(Eina_Share_Common_Head *bucket, int hash) +{ + return (Eina_Share_Common_Head *)eina_rbtree_inline_lookup + (EINA_RBTREE_GET(bucket), &hash, 0, + EINA_RBTREE_CMP_KEY_CB(_eina_share_common_cmp), NULL); +} + +static Eina_Share_Common_Node * +_eina_share_common_node_alloc(unsigned int slen, unsigned int null_size) +{ + Eina_Share_Common_Node *node; + const size_t node_size = offsetof(Eina_Share_Common_Node, str); + + node = malloc(node_size + slen + null_size); + if (!node) + eina_error_set(EINA_ERROR_OUT_OF_MEMORY); + + return node; +} + +static Eina_Share_Common_Node * +_eina_share_common_node_from_str(const char *str, Eina_Magic node_magic) +{ + Eina_Share_Common_Node *node; + const size_t offset = offsetof(Eina_Share_Common_Node, str); + + node = (Eina_Share_Common_Node *)(str - offset); + EINA_MAGIC_CHECK_SHARE_COMMON_NODE(node, node_magic, node = NULL); + return node; + + (void) node_magic; /* When magic are disable, node_magic is unused, this remove a warning. */ +} + +static Eina_Bool +eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, + Eina_Share_Common_Head *head, + struct dumpinfo *fdata) +{ + Eina_Share_Common_Node *node; + + fdata->used += sizeof(Eina_Share_Common_Head); + for (node = head->head; node; node = node->next) + { + printf("DDD: %5i %5i ", node->length, node->references); + printf("'%.*s'\n", node->length, ((char *)node) + sizeof(Eina_Share_Common_Node)); + fdata->used += sizeof(Eina_Share_Common_Node); + fdata->used += node->length; + fdata->saved += (node->references - 1) * node->length; + fdata->dups += node->references - 1; + fdata->unique++; + } + + return EINA_TRUE; +} + +/** + * @endcond + */ + + +/*============================================================================* +* Global * +*============================================================================*/ + +/** + * @internal + * @brief Initialize the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function sets up the share_common module of Eina. It is called by + * eina_init(). + * + * @see eina_init() + */ +Eina_Bool +eina_share_common_init(Eina_Share **_share, + Eina_Magic node_magic, + const char *node_magic_STR) +{ + Eina_Share *share; + + share = *_share = calloc(sizeof(Eina_Share), 1); + if (!share) goto on_error; + + if (_eina_share_common_log_dom < 0) /*Only register if not already */ + _eina_share_common_log_dom = eina_log_domain_register( + "eina_share", + EINA_LOG_COLOR_DEFAULT); + + if (_eina_share_common_log_dom < 0) + { + EINA_LOG_ERR("Could not register log domain: eina_share_common"); + goto on_error; + } + + share->share = calloc(1, sizeof(Eina_Share_Common)); + if (!share->share) + { + if (_eina_share_common_log_dom > 0) + { + eina_log_domain_unregister(_eina_share_common_log_dom); + _eina_share_common_log_dom = -1; + } + + goto on_error; + } + + share->node_magic = node_magic; +#define EMS(n) eina_magic_string_static_set(n, n ## _STR) + EMS(EINA_MAGIC_SHARE); + EMS(EINA_MAGIC_SHARE_HEAD); + EMS(node_magic); +#undef EMS + EINA_MAGIC_SET(share->share, EINA_MAGIC_SHARE); + + _eina_share_common_population_init(share); + + /* below is the common part among other all eina_share_common user */ + if (_eina_share_common_count++ != 0) + return EINA_TRUE; + + eina_lock_new(&_mutex_big); + return EINA_TRUE; + + on_error: + _eina_share_common_count--; + return EINA_FALSE; +} + +/** + * @internal + * @brief Shut down the share_common module. + * + * @return #EINA_TRUE on success, #EINA_FALSE on failure. + * + * This function shuts down the share_common module set up by + * eina_share_common_init(). It is called by eina_shutdown(). + * + * @see eina_shutdown() + */ +Eina_Bool +eina_share_common_shutdown(Eina_Share **_share) +{ + unsigned int i; + Eina_Share *share = *_share; + + eina_lock_take(&_mutex_big); + + _eina_share_common_population_stats(share); + + /* remove any string still in the table */ + for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) + { + eina_rbtree_delete(EINA_RBTREE_GET( + share->share->buckets[i]), + EINA_RBTREE_FREE_CB( + _eina_share_common_head_free), NULL); + share->share->buckets[i] = NULL; + } + MAGIC_FREE(share->share); + + _eina_share_common_population_shutdown(share); + if (_eina_share_common_log_dom > 0) /* Only free if necessary */ + { + eina_log_domain_unregister(_eina_share_common_log_dom); + _eina_share_common_log_dom = -1; + } + + eina_lock_release(&_mutex_big); + + free(*_share); + *_share = NULL; + + /* below is the common part among other all eina_share_common user */ + if (--_eina_share_common_count != 0) + return EINA_TRUE; + + eina_lock_free(&_mutex_big); + + return EINA_TRUE; +} + +#ifdef EFL_HAVE_THREADS + +/** + * @internal + * @brief Activate the share_common mutexes. + * + * This function activate the mutexes in the eina share_common module. It is called by + * eina_threads_init(). + * + * @see eina_threads_init() + */ +void +eina_share_common_threads_init(void) +{ + _share_common_threads_activated = EINA_TRUE; +} + +/** + * @internal + * @brief Shut down the share_common mutexes. + * + * This function shuts down the mutexes in the share_common module. + * It is called by eina_threads_shutdown(). + * + * @see eina_threads_shutdown() + */ +void +eina_share_common_threads_shutdown(void) +{ + _share_common_threads_activated = EINA_FALSE; +} + +#endif + +/*============================================================================* +* API * +*============================================================================*/ + +/** + * @cond LOCAL + */ + +const char * +eina_share_common_add_length(Eina_Share *share, + const char *str, + unsigned int slen, + unsigned int null_size) +{ + Eina_Share_Common_Head **p_bucket, *ed; + Eina_Share_Common_Node *el; + int hash_num, hash; + + if (!str) + return NULL; + + eina_share_common_population_add(share, slen); + + if (slen <= 0) + return NULL; + + hash = eina_hash_superfast(str, slen); + hash_num = hash & 0xFF; + hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; + + eina_lock_take(&_mutex_big); + p_bucket = share->share->buckets + hash_num; + + ed = _eina_share_common_find_hash(*p_bucket, hash); + if (!ed) + { + const char *s = _eina_share_common_add_head(share, + p_bucket, + hash, + str, + slen, + null_size); + eina_lock_release(&_mutex_big); + return s; + } + + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big), NULL); + + el = _eina_share_common_head_find(ed, str, slen); + if (el) + { + EINA_MAGIC_CHECK_SHARE_COMMON_NODE(el, + share->node_magic, + eina_lock_release(&_mutex_big)); + el->references++; + eina_lock_release(&_mutex_big); + return el->str; + } + + el = _eina_share_common_node_alloc(slen, null_size); + if (!el) + { + eina_lock_release(&_mutex_big); + return NULL; + } + + _eina_share_common_node_init(el, str, slen, null_size, share->node_magic); + el->next = ed->head; + ed->head = el; + _eina_share_common_population_head_add(share, ed); + + eina_lock_release(&_mutex_big); + + return el->str; +} + +const char * +eina_share_common_ref(Eina_Share *share, const char *str) +{ + Eina_Share_Common_Node *node; + + if (!str) + return NULL; + + eina_lock_take(&_mutex_big); + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) + { + eina_lock_release(&_mutex_big); + return str; + } + node->references++; + + eina_lock_release(&_mutex_big); + + eina_share_common_population_add(share, node->length); + + return str; +} + + +void +eina_share_common_del(Eina_Share *share, const char *str) +{ + unsigned int slen; + Eina_Share_Common_Head *ed; + Eina_Share_Common_Head **p_bucket; + Eina_Share_Common_Node *node; + int hash_num, hash; + + if (!str) + return; + + eina_lock_take(&_mutex_big); + + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) + goto on_error; + + slen = node->length; + eina_share_common_population_del(share, slen); + if (node->references > 1) + { + node->references--; + eina_lock_release(&_mutex_big); + return; + } + + node->references = 0; + + hash = eina_hash_superfast(str, slen); + hash_num = hash & 0xFF; + hash = (hash >> 8) & EINA_SHARE_COMMON_MASK; + + p_bucket = share->share->buckets + hash_num; + ed = _eina_share_common_find_hash(*p_bucket, hash); + if (!ed) + goto on_error; + + EINA_MAGIC_CHECK_SHARE_COMMON_HEAD(ed, eina_lock_release(&_mutex_big)); + + if (!_eina_share_common_head_remove_node(ed, node)) + goto on_error; + + if (node != &ed->builtin_node) + MAGIC_FREE(node); + + if (!ed->head) + _eina_share_common_del_head(p_bucket, ed); + else + _eina_share_common_population_head_del(share, ed); + + eina_lock_release(&_mutex_big); + + return; + +on_error: + eina_lock_release(&_mutex_big); + /* possible segfault happened before here, but... */ + CRITICAL("EEEK trying to del non-shared share_common \"%s\"", str); +} + +int +eina_share_common_length(__UNUSED__ Eina_Share *share, const char *str) +{ + const Eina_Share_Common_Node *node; + + if (!str) + return -1; + + node = _eina_share_common_node_from_str(str, share->node_magic); + if (!node) return 0; + return node->length; +} + +void +eina_share_common_dump(Eina_Share *share, void (*additional_dump)( + struct dumpinfo *), int used) +{ + Eina_Iterator *it; + unsigned int i; + struct dumpinfo di; + + if (!share) + return; + + di.used = used; + di.saved = 0; + di.dups = 0; + di.unique = 0; + printf("DDD: len ref string\n"); + printf("DDD:-------------------\n"); + + eina_lock_take(&_mutex_big); + for (i = 0; i < EINA_SHARE_COMMON_BUCKETS; i++) + { + if (!share->share->buckets[i]) + { + continue; // printf("DDD: BUCKET # %i (HEAD=%i, NODE=%i)\n", i, + + } + +// sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node)); + it = eina_rbtree_iterator_prefix( + (Eina_Rbtree *)share->share->buckets[i]); + eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di); + eina_iterator_free(it); + } + if (additional_dump) + additional_dump(&di); + +#ifdef EINA_SHARE_COMMON_USAGE + /* One character strings are not counted in the hash. */ + di.saved += share->population_group[0].count * sizeof(char); + di.saved += share->population_group[1].count * sizeof(char) * 2; +#endif + printf("DDD:-------------------\n"); + printf("DDD: usage (bytes) = %i, saved = %i (%3.0f%%)\n", + di.used, di.saved, di.used ? (di.saved * 100.0 / di.used) : 0.0); + printf("DDD: unique: %d, duplicates: %d (%3.0f%%)\n", + di.unique, di.dups, di.unique ? (di.dups * 100.0 / di.unique) : 0.0); + +#ifdef EINA_SHARE_COMMON_USAGE + printf("DDD: Allocated strings: %i\n", share->population.count); + printf("DDD: Max allocated strings: %i\n", share->population.max); + + for (i = 0; + i < sizeof (share->population_group) / + sizeof (share->population_group[0]); + ++i) + fprintf(stderr, + "DDD: %i strings of length %i, max strings: %i\n", + share->population_group[i].count, + i, + share->population_group[i].max); +#endif + + eina_lock_release(&_mutex_big); +} + +/** + * @endcond + */ -- cgit v1.1