forked from enlightenment/efl
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:
parent
b2ac7c110a
commit
6ea6dc0856
|
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue