Eina : now eina stringshare is thread safe if eina_threads_init() is called. Eina log which was thread safe is now thread safe only if the previous functions is called

SVN revision: 43398
This commit is contained in:
Jonathan Atton 2009-11-01 19:50:18 +00:00
parent b2ac7c110a
commit 6ea6dc0856
6 changed files with 306 additions and 39 deletions

View File

@ -35,6 +35,10 @@ EAPI int eina_init(void);
EAPI int eina_shutdown(void); EAPI int eina_shutdown(void);
EAPI int eina_threads_init(void);
EAPI int eina_threads_shutdown(void);
/** /**
* @} * @}
*/ */

View File

@ -116,5 +116,12 @@
} \ } \
} while(0); } while(0);
#ifdef EFL_HAVE_PTHREAD
void eina_stringshare_threads_init(void);
void eina_stringshare_threads_shutdown(void);
void eina_log_threads_init(void);
void eina_log_threads_shutdown(void);
#endif
#endif /* EINA_PRIVATE_H_ */ #endif /* EINA_PRIVATE_H_ */

View File

@ -1,3 +1,5 @@
// vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
/* EINA - EFL data type library /* EINA - EFL data type library
* Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck, * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck,
* Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga, * Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga,
@ -1590,15 +1592,15 @@ eina_list_merge(Eina_List *left, Eina_List *right)
* @param right The head of the new right list. * @param right The head of the new right list.
* @return The new left list * @return The new left list
* *
* This function split @p list into two lists ( left and right ) after the node @p relative. @p Relative * This function split @p list into two lists ( left and right ) after the node @p relative. @p Relative
* will become the last node of the left list. If @p list or @p right are NULL list is returns. * will become the last node of the left list. If @p list or @p right are NULL list is returns.
* If @p relative is NULL right is set to @p list and NULL is returns. * If @p relative is NULL right is set to @p list and NULL is returns.
* If @p relative is the last node of @p list list is returns and @p right is set to NULL. * If @p relative is the last node of @p list list is returns and @p right is set to NULL.
* *
* list does not exist anymore after the split. * list does not exist anymore after the split.
* *
*/ */
EAPI Eina_List * EAPI Eina_List *
eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right) eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
{ {
Eina_List *next; Eina_List *next;
@ -1610,12 +1612,12 @@ eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
if (!list) return NULL; if (!list) return NULL;
if (!relative) if (!relative)
{ {
*right = list; *right = list;
return NULL; return NULL;
} }
if (relative == eina_list_last(list)) return list; if (relative == eina_list_last(list)) return list;
next = eina_list_next(relative); next = eina_list_next(relative);
next->prev = NULL; next->prev = NULL;
next->accounting = _eina_list_mempool_accounting_new(next); next->accounting = _eina_list_mempool_accounting_new(next);
next->accounting->last = list->accounting->last; next->accounting->last = list->accounting->last;
@ -1624,14 +1626,14 @@ eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
itr = next; itr = next;
do do
{ {
itr->accounting = next->accounting; itr->accounting = next->accounting;
next->accounting->count++; next->accounting->count++;
itr = itr->next; itr = itr->next;
} }
while (itr); while (itr);
relative->next = NULL; relative->next = NULL;
list->accounting->last = relative; list->accounting->last = relative;
list->accounting->count = list->accounting->count - next->accounting->count; list->accounting->count = list->accounting->count - next->accounting->count;
return list; return list;

View File

@ -376,6 +376,7 @@ static pthread_t _main_thread;
#ifdef EINA_PTHREAD_SPIN #ifdef EINA_PTHREAD_SPIN
static pthread_spinlock_t _log_lock; static pthread_spinlock_t _log_lock;
#define LOCK() \ #define LOCK() \
if(_threads_enabled) \
do { \ do { \
if (0) \ if (0) \
fprintf(stderr, "+++LOG LOCKED! [%s, %lu]\n", \ fprintf(stderr, "+++LOG LOCKED! [%s, %lu]\n", \
@ -384,6 +385,7 @@ static pthread_spinlock_t _log_lock;
pthread_spin_lock(&_log_lock); \ pthread_spin_lock(&_log_lock); \
} while (0) } while (0)
#define UNLOCK() \ #define UNLOCK() \
if(_threads_enabled) \
do { \ do { \
if (EINA_UNLIKELY(_threads_enabled)) \ if (EINA_UNLIKELY(_threads_enabled)) \
pthread_spin_unlock(&_log_lock); \ pthread_spin_unlock(&_log_lock); \
@ -396,8 +398,8 @@ static pthread_spinlock_t _log_lock;
#define SHUTDOWN() pthread_spin_destroy(&_log_lock); #define SHUTDOWN() pthread_spin_destroy(&_log_lock);
#else #else
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
#define LOCK() pthread_mutex_lock(&_log_mutex); #define LOCK() if(_threads_enabled) pthread_mutex_lock(&_log_mutex);
#define UNLOCK() pthread_mutex_unlock(&_log_mutex); #define UNLOCK() if(_threads_enabled) pthread_mutex_unlock(&_log_mutex);
#define INIT() do {} while (0) #define INIT() do {} while (0)
#define SHUTDOWN() do {} while (0) #define SHUTDOWN() do {} while (0)
#endif #endif
@ -700,7 +702,6 @@ eina_log_print_prefix_update(void)
#undef S #undef S
} }
/* /*
* Creates a colored domain name string. * Creates a colored domain name string.
*/ */
@ -965,11 +966,6 @@ eina_log_init(void)
assert((sizeof(_names)/sizeof(_names[0])) == EINA_LOG_LEVELS); assert((sizeof(_names)/sizeof(_names[0])) == EINA_LOG_LEVELS);
assert((sizeof(_colors)/sizeof(_colors[0])) == EINA_LOG_LEVELS + 1); assert((sizeof(_colors)/sizeof(_colors[0])) == EINA_LOG_LEVELS + 1);
#ifdef EFL_HAVE_PTHREAD
_main_thread = pthread_self();
INIT();
#endif
// Check if color is disabled // Check if color is disabled
if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)) && (atoi(tmp) == 1)) if ((tmp = getenv(EINA_LOG_ENV_COLOR_DISABLE)) && (atoi(tmp) == 1))
_disable_color = EINA_TRUE; _disable_color = EINA_TRUE;
@ -1056,14 +1052,48 @@ eina_log_shutdown(void)
free(tmp); free(tmp);
} }
#ifdef EFL_HAVE_PTHREAD
SHUTDOWN();
_threads_enabled = 0;
#endif
return EINA_TRUE; return EINA_TRUE;
} }
#ifdef EFL_HAVE_PTHREAD
/**
* @internal
* @brief Activate the log mutex.
*
* This function activate the mutex in the eina log module. It is called by
* eina_thread_init().
*
* @see eina_thread_init()
*/
void
eina_log_threads_init(void)
{
_main_thread = pthread_self();
_threads_enabled = EINA_TRUE;
INIT();
}
/**
* @internal
* @brief Shut down the log mutex.
*
* This function shuts down the mutex in the log module.
* It is called by eina_thread_shutdown().
*
* @see eina_thread_shutdown()
*/
void
eina_log_threads_shutdown(void)
{
SHUTDOWN();
_threads_enabled = EINA_FALSE;
}
#endif
/** /**
* Enable logging module to handle threads. * Enable logging module to handle threads.
* *
@ -1471,3 +1501,4 @@ eina_log_vprint(int domain, Eina_Log_Level level, const char *file,
eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args); eina_log_print_unlocked(domain, level, file, fnc, line, fmt, args);
UNLOCK(); UNLOCK();
} }

View File

@ -48,6 +48,7 @@
*/ */
static int _eina_main_count = 0; static int _eina_main_count = 0;
static int _eina_main_thread_count = 0;
static int _eina_log_dom = -1; static int _eina_log_dom = -1;
#ifdef ERR #ifdef ERR
@ -60,6 +61,18 @@ static int _eina_log_dom = -1;
#endif #endif
#define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__) #define DBG(...) EINA_LOG_DOM_DBG(_eina_log_dom, __VA_ARGS__)
#ifdef EFL_HAVE_PTHREAD
#include <pthread.h>
static Eina_Bool _threads_activated = EINA_FALSE;
static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
#define LOCK() if(_threads_activated) pthread_mutex_lock(&_mutex);
#define UNLOCK() if(_threads_activated) pthread_mutex_unlock(&_mutex);
#define UNLOCK_FORCE() pthread_mutex_unlock(&_mutex);
#else
#define LOCK() do {} while (0)
#define UNLOCK() do {} while (0)
#define UNLOCK_FORCE() do {} while (0)
#endif
/* place module init/shutdown functions here to avoid other modules /* place module init/shutdown functions here to avoid other modules
* calling them by mistake. * calling them by mistake.
@ -220,6 +233,88 @@ eina_shutdown(void)
return _eina_main_count; return _eina_main_count;
} }
/**
* @brief Initialize the mutexs of the Eina library.
*
* @return 1 or greater on success, 0 on error.
*
* This function sets up all the mutexs in all eina modules. It returns 0 on
* failure (that is, when one of the module fails to initialize),
* otherwise it returns the number of times it has already been
* called.
*
* When the mutexs are not used anymore, call eina_thread_shutdown() to shut down
* the mutexs.
*/
EAPI int
eina_threads_init(void)
{
#ifdef EFL_HAVE_PTHREAD
int ret;
LOCK();
++_eina_main_thread_count;
ret = _eina_main_thread_count;
if(_eina_main_thread_count > 1)
{
UNLOCK();
return ret;
}
eina_stringshare_threads_init();
eina_log_threads_init();
_threads_activated = EINA_TRUE;
return ret;
#else
return 0;
#endif
}
/**
* @brief Shut down mutexs in the Eina library.
*
* @return 0 when all mutexs are completely shut down, 1 or
* greater otherwise.
*
* This function shuts down the mutexs in the Eina library. It returns 0 when it has
* been called the same number of times than eina_thread_init(). In that case
* it shut down all the mutexs.
*
* Once this function succeeds (that is, @c 0 is returned), you must
* not call any of the Eina function in a thread anymore. You must call
* eina_thread_init() again to use the Eina functions in a thread again.
*/
EAPI int
eina_threads_shutdown(void)
{
#ifdef EFL_HAVE_PTHREAD
int ret;
LOCK();
ret = --_eina_main_thread_count;
if(_eina_main_thread_count > 0)
{
UNLOCK();
return ret;
}
eina_stringshare_threads_shutdown();
eina_log_threads_shutdown();
_threads_activated = EINA_FALSE;
UNLOCK_FORCE();
return ret;
#else
return 0;
#endif
}
/** /**
* @} * @}
*/ */

View File

@ -100,19 +100,23 @@ static const char EINA_MAGIC_STRINGSHARE_HEAD_STR[] = "Eina Stringshare Head";
static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node"; static const char EINA_MAGIC_STRINGSHARE_NODE_STR[] = "Eina Stringshare Node";
#define EINA_MAGIC_CHECK_STRINGSHARE_HEAD(d, ...) \ #define EINA_MAGIC_CHECK_STRINGSHARE_HEAD(d, unlock, ...) \
do { \ do { \
if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRINGSHARE_HEAD)) \ if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRINGSHARE_HEAD)) \
{ \ { \
EINA_MAGIC_FAIL((d), EINA_MAGIC_STRINGSHARE_HEAD); \ EINA_MAGIC_FAIL((d), EINA_MAGIC_STRINGSHARE_HEAD); \
unlock; \
return __VA_ARGS__; \ return __VA_ARGS__; \
} \ } \
} while (0); } while (0);
#define EINA_MAGIC_CHECK_STRINGSHARE_NODE(d) \ #define EINA_MAGIC_CHECK_STRINGSHARE_NODE(d, unlock) \
do { \ do { \
if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRINGSHARE_NODE)) \ if (!EINA_MAGIC_CHECK((d), EINA_MAGIC_STRINGSHARE_NODE)) \
{ \
unlock; \
EINA_MAGIC_FAIL((d), EINA_MAGIC_STRINGSHARE_NODE); \ EINA_MAGIC_FAIL((d), EINA_MAGIC_STRINGSHARE_NODE); \
} \
} while (0); } while (0);
typedef struct _Eina_Stringshare Eina_Stringshare; typedef struct _Eina_Stringshare Eina_Stringshare;
@ -170,6 +174,27 @@ static int _eina_stringshare_log_dom = -1;
#endif #endif
#define DBG(...) EINA_LOG_DOM_DBG(_eina_stringshare_log_dom, __VA_ARGS__) #define DBG(...) EINA_LOG_DOM_DBG(_eina_stringshare_log_dom, __VA_ARGS__)
#ifdef EFL_HAVE_PTHREAD
#include <pthread.h>
static Eina_Bool _threads_activated = EINA_FALSE;
//string < 4
static pthread_mutex_t _mutex_small = PTHREAD_MUTEX_INITIALIZER;
//string >= 4
static pthread_mutex_t _mutex_big = PTHREAD_MUTEX_INITIALIZER;
#define LOCK_SMALL() if(_threads_activated) pthread_mutex_lock(&_mutex_small);
#define UNLOCK_SMALL() if(_threads_activated) pthread_mutex_unlock(&_mutex_small);
#define LOCK_BIG() if(_threads_activated) pthread_mutex_lock(&_mutex_big);
#define UNLOCK_BIG() if(_threads_activated) pthread_mutex_unlock(&_mutex_big);
#else
#define LOCK_SMALL() do {} while (0)
#define UNLOCK_SMALL() do {} while (0)
#define LOCK_BIG() do {} while (0)
#define UNLOCK_BIG() do {} while (0)
#endif
static const unsigned char _eina_stringshare_single[512] = { static const unsigned char _eina_stringshare_single[512] = {
0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0, 0,0,1,0,2,0,3,0,4,0,5,0,6,0,7,0,8,0,9,0,10,0,11,0,12,0,13,0,14,0,15,0,
16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0, 16,0,17,0,18,0,19,0,20,0,21,0,22,0,23,0,24,0,25,0,26,0,27,0,28,0,29,0,30,0,
@ -276,6 +301,9 @@ _eina_stringshare_population_stats(void)
static void static void
_eina_stringshare_population_add(int slen) _eina_stringshare_population_add(int slen)
{ {
LOCK_SMALL();
LOCK_BIG();
population.count++; population.count++;
if (population.count > population.max) if (population.count > population.max)
population.max = population.count; population.max = population.count;
@ -286,14 +314,23 @@ _eina_stringshare_population_add(int slen)
if (population_group[slen].count > population_group[slen].max) if (population_group[slen].count > population_group[slen].max)
population_group[slen].max = population_group[slen].count; population_group[slen].max = population_group[slen].count;
} }
UNLOCK_BIG();
UNLOCK_SMALL();
} }
static void static void
_eina_stringshare_population_del(int slen) _eina_stringshare_population_del(int slen)
{ {
LOCK_SMALL();
LOCK_BIG();
population.count--; population.count--;
if (slen < 4) if (slen < 4)
population_group[slen].count--; population_group[slen].count--;
UNLOCK_BIG();
UNLOCK_SMALL();
} }
static void static void
@ -331,7 +368,7 @@ static void _eina_stringshare_population_head_del(__UNUSED__ Eina_Stringshare_He
static int static int
_eina_stringshare_cmp(const Eina_Stringshare_Head *ed, const int *hash, __UNUSED__ int length, __UNUSED__ void *data) _eina_stringshare_cmp(const Eina_Stringshare_Head *ed, const int *hash, __UNUSED__ int length, __UNUSED__ void *data)
{ {
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, 0); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, , 0);
return ed->hash - *hash; return ed->hash - *hash;
} }
@ -339,8 +376,8 @@ _eina_stringshare_cmp(const Eina_Stringshare_Head *ed, const int *hash, __UNUSED
static Eina_Rbtree_Direction static Eina_Rbtree_Direction
_eina_stringshare_node(const Eina_Stringshare_Head *left, const Eina_Stringshare_Head *right, __UNUSED__ void *data) _eina_stringshare_node(const Eina_Stringshare_Head *left, const Eina_Stringshare_Head *right, __UNUSED__ void *data)
{ {
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(left, 0); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(left, , 0);
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(right, 0); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(right, , 0);
if (left->hash - right->hash < 0) if (left->hash - right->hash < 0)
return EINA_RBTREE_LEFT; return EINA_RBTREE_LEFT;
@ -350,7 +387,7 @@ _eina_stringshare_node(const Eina_Stringshare_Head *left, const Eina_Stringshare
static void static void
_eina_stringshare_head_free(Eina_Stringshare_Head *ed, __UNUSED__ void *data) _eina_stringshare_head_free(Eina_Stringshare_Head *ed, __UNUSED__ void *data)
{ {
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, );
while (ed->head) while (ed->head)
{ {
@ -879,6 +916,9 @@ eina_stringshare_shutdown(void)
{ {
unsigned int i; unsigned int i;
LOCK_SMALL();
LOCK_BIG();
_eina_stringshare_population_stats(); _eina_stringshare_population_stats();
/* remove any string still in the table */ /* remove any string still in the table */
@ -893,9 +933,48 @@ eina_stringshare_shutdown(void)
_eina_stringshare_small_shutdown(); _eina_stringshare_small_shutdown();
eina_log_domain_unregister(_eina_stringshare_log_dom); eina_log_domain_unregister(_eina_stringshare_log_dom);
_eina_stringshare_log_dom = -1; _eina_stringshare_log_dom = -1;
UNLOCK_BIG();
UNLOCK_SMALL();
return EINA_TRUE; return EINA_TRUE;
} }
#ifdef EFL_HAVE_PTHREAD
/**
* @internal
* @brief Activate the stringshare mutexs.
*
* This function activate the mutexs in the eina stringshare module. It is called by
* eina_thread_init().
*
* @see eina_thread_init()
*/
void
eina_stringshare_threads_init(void)
{
_threads_activated = EINA_TRUE;
}
/**
* @internal
* @brief Shut down the stringshare mutexs.
*
* This function shuts down the mutexs in the stringshare module.
* It is called by eina_thread_shutdown().
*
* @see eina_thread_shutdown()
*/
void
eina_stringshare_threads_shutdown(void)
{
_threads_activated = EINA_FALSE;
}
#endif
/** /**
* @brief Retrieve an instance of a string for use in a program. * @brief Retrieve an instance of a string for use in a program.
* *
@ -936,36 +1015,53 @@ eina_stringshare_add_length(const char *str, unsigned int slen)
else if (slen == 1) else if (slen == 1)
return (const char *)_eina_stringshare_single + ((*str) << 1); return (const char *)_eina_stringshare_single + ((*str) << 1);
else if (slen < 4) else if (slen < 4)
return _eina_stringshare_small_add(str, slen); {
LOCK_SMALL();
const char *s = _eina_stringshare_small_add(str, slen);
UNLOCK_SMALL();
return s;
}
hash = eina_hash_superfast(str, slen); hash = eina_hash_superfast(str, slen);
hash_num = hash & 0xFF; hash_num = hash & 0xFF;
hash = (hash >> 8) & EINA_STRINGSHARE_MASK; hash = (hash >> 8) & EINA_STRINGSHARE_MASK;
LOCK_BIG();
p_bucket = share->buckets + hash_num; p_bucket = share->buckets + hash_num;
ed = _eina_stringshare_find_hash(*p_bucket, hash); ed = _eina_stringshare_find_hash(*p_bucket, hash);
if (!ed) if (!ed)
return _eina_stringshare_add_head(p_bucket, hash, str, slen); {
const char *s = _eina_stringshare_add_head(p_bucket, hash, str, slen);
UNLOCK_BIG();
return s;
}
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, NULL); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, UNLOCK_BIG(), NULL);
el = _eina_stringshare_head_find(ed, str, slen); el = _eina_stringshare_head_find(ed, str, slen);
if (el) if (el)
{ {
EINA_MAGIC_CHECK_STRINGSHARE_NODE(el); EINA_MAGIC_CHECK_STRINGSHARE_NODE(el, UNLOCK_BIG());
el->references++; el->references++;
UNLOCK_BIG();
return el->str; return el->str;
} }
el = _eina_stringshare_node_alloc(slen); el = _eina_stringshare_node_alloc(slen);
if (!el) if (!el)
return NULL; {
UNLOCK_BIG();
return NULL;
}
_eina_stringshare_node_init(el, str, slen); _eina_stringshare_node_init(el, str, slen);
el->next = ed->head; el->next = ed->head;
ed->head = el; ed->head = el;
_eina_stringshare_population_head_add(ed); _eina_stringshare_population_head_add(ed);
UNLOCK_BIG();
return el->str; return el->str;
} }
@ -1014,7 +1110,7 @@ _eina_stringshare_node_from_str(const char *str)
const size_t offset = (char *)&(t.str) - (char *)&t; const size_t offset = (char *)&(t.str) - (char *)&t;
node = (Eina_Stringshare_Node *)(str - offset); node = (Eina_Stringshare_Node *)(str - offset);
EINA_MAGIC_CHECK_STRINGSHARE_NODE(node); EINA_MAGIC_CHECK_STRINGSHARE_NODE(node, );
return node; return node;
} }
@ -1047,18 +1143,27 @@ eina_stringshare_ref(const char *str)
if (slen < 2) if (slen < 2)
{ {
_eina_stringshare_population_add(slen); _eina_stringshare_population_add(slen);
return str; return str;
} }
else if (slen < 4) else if (slen < 4)
{ {
_eina_stringshare_population_add(slen); _eina_stringshare_population_add(slen);
return _eina_stringshare_small_add(str, slen);
LOCK_SMALL();
const char *s = _eina_stringshare_small_add(str, slen);
UNLOCK_SMALL();
return s;
} }
LOCK_BIG();
node = _eina_stringshare_node_from_str(str); node = _eina_stringshare_node_from_str(str);
node->references++; node->references++;
DBG("str=%p (%s) refs=%u", str, str, node->references); DBG("str=%p (%s) refs=%u", str, str, node->references);
UNLOCK_BIG();
_eina_stringshare_population_add(node->length); _eina_stringshare_population_add(node->length);
return str; return str;
@ -1102,15 +1207,20 @@ eina_stringshare_del(const char *str)
return; return;
else if (slen < 4) else if (slen < 4)
{ {
LOCK_SMALL();
_eina_stringshare_small_del(str, slen); _eina_stringshare_small_del(str, slen);
UNLOCK_SMALL();
return; return;
} }
LOCK_BIG();
node = _eina_stringshare_node_from_str(str); node = _eina_stringshare_node_from_str(str);
if (node->references > 1) if (node->references > 1)
{ {
node->references--; node->references--;
DBG("str=%p (%s) refs=%u", str, str, node->references); DBG("str=%p (%s) refs=%u", str, str, node->references);
UNLOCK_BIG();
return; return;
} }
@ -1127,7 +1237,7 @@ eina_stringshare_del(const char *str)
if (!ed) if (!ed)
goto on_error; goto on_error;
EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed); EINA_MAGIC_CHECK_STRINGSHARE_HEAD(ed, UNLOCK_BIG());
if (!_eina_stringshare_head_remove_node(ed, node)) if (!_eina_stringshare_head_remove_node(ed, node))
goto on_error; goto on_error;
@ -1140,9 +1250,12 @@ eina_stringshare_del(const char *str)
else else
_eina_stringshare_population_head_del(ed); _eina_stringshare_population_head_del(ed);
UNLOCK_BIG();
return; return;
on_error: on_error:
UNLOCK_BIG();
/* possible segfault happened before here, but... */ /* possible segfault happened before here, but... */
CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str); CRITICAL("EEEK trying to del non-shared stringshare \"%s\"", str);
} }
@ -1231,7 +1344,10 @@ static Eina_Bool
eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, Eina_Stringshare_Head *head, struct dumpinfo *fdata) eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, Eina_Stringshare_Head *head, struct dumpinfo *fdata)
{ {
Eina_Stringshare_Node *node; Eina_Stringshare_Node *node;
LOCK_SMALL();
LOCK_BIG();
fdata->used += sizeof(Eina_Stringshare_Head); fdata->used += sizeof(Eina_Stringshare_Head);
for (node = head->head; node; node = node->next) for (node = head->head; node; node = node->next)
{ {
@ -1243,6 +1359,10 @@ eina_iterator_array_check(const Eina_Rbtree *rbtree __UNUSED__, Eina_Stringshare
fdata->dups += node->references - 1; fdata->dups += node->references - 1;
fdata->unique++; fdata->unique++;
} }
UNLOCK_BIG();
UNLOCK_SMALL();
return EINA_TRUE; return EINA_TRUE;
} }
@ -1266,7 +1386,12 @@ eina_stringshare_dump(void)
di.unique = 0; di.unique = 0;
printf("DDD: len ref string\n"); printf("DDD: len ref string\n");
printf("DDD:-------------------\n"); printf("DDD:-------------------\n");
LOCK_SMALL();
_eina_stringshare_small_dump(&di); _eina_stringshare_small_dump(&di);
UNLOCK_SMALL();
LOCK_BIG();
for (i = 0; i < EINA_STRINGSHARE_BUCKETS; i++) for (i = 0; i < EINA_STRINGSHARE_BUCKETS; i++)
{ {
if (!share->buckets[i]) continue; if (!share->buckets[i]) continue;
@ -1294,8 +1419,11 @@ eina_stringshare_dump(void)
for (i = 0; i < sizeof (population_group) / sizeof (population_group[0]); ++i) for (i = 0; i < sizeof (population_group) / sizeof (population_group[0]); ++i)
fprintf(stderr, "DDD: %i strings of length %i, max strings: %i\n", population_group[i].count, i, population_group[i].max); fprintf(stderr, "DDD: %i strings of length %i, max strings: %i\n", population_group[i].count, i, population_group[i].max);
#endif #endif
UNLOCK_BIG();
} }
/** /**
* @} * @}
*/ */