implement threadsafety for arrays, alter all eina internal array usage to (hopefully) be threadsafe

call eina_threads_init() to enable this if you have pthread rwlock support (posix 2001)
note some function prototypes have lost const on array params to allow locking
WARNING: you should NOT call eina_threads_shutdown unless you are positive that you will not use any arrays which were created while threadsafe mode were enabled, and vice versa.  Failing to adhere to this warning WILL result in either deadlocks or memory leaks.


SVN revision: 50951
This commit is contained in:
Mike Blumenkrantz 2010-08-10 03:26:15 +00:00
parent ccfd7f27fc
commit 56a0bd9396
14 changed files with 424 additions and 111 deletions

View File

@ -66,9 +66,12 @@ typedef void **Eina_Array_Iterator;
struct _Eina_Array
{
void **data; /**< Pointer to a vector of pointer to payload */
unsigned int total; /**< Total number of slot in the vector */
unsigned int count; /**< Number of activ slot in the vector */
unsigned int total; /**< Total number of slots in the vector */
unsigned int count; /**< Number of active slots in the vector */
unsigned int step; /**< How much must we grow the vector when it is full */
#ifdef EINA_RWLOCKS_ENABLED
pthread_rwlock_t lock;
#endif
EINA_MAGIC
};
@ -82,12 +85,12 @@ EAPI Eina_Bool eina_array_remove(Eina_Array *array, Eina_Bool(*
static inline Eina_Bool eina_array_push(Eina_Array *array, const void *data) EINA_ARG_NONNULL(1, 2);
static inline void * eina_array_pop(Eina_Array *array) EINA_ARG_NONNULL(1);
static inline void * eina_array_data_get(const Eina_Array *array, unsigned int idx) EINA_ARG_NONNULL(1);
static inline void eina_array_data_set(const Eina_Array *array, unsigned int idx, const void *data) EINA_ARG_NONNULL(1, 3);
static inline unsigned int eina_array_count_get(const Eina_Array *array) EINA_ARG_NONNULL(1);
static inline void * eina_array_data_get(Eina_Array *array, unsigned int idx) EINA_ARG_NONNULL(1);
static inline void eina_array_data_set(Eina_Array *array, unsigned int idx, const void *data) EINA_ARG_NONNULL(1, 3);
static inline unsigned int eina_array_count_get(Eina_Array *array) EINA_ARG_NONNULL(1);
EAPI Eina_Iterator * eina_array_iterator_new(const Eina_Array *array) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI Eina_Accessor * eina_array_accessor_new(const Eina_Array *array) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI Eina_Iterator * eina_array_iterator_new(Eina_Array *array) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
EAPI Eina_Accessor * eina_array_accessor_new(Eina_Array *array) EINA_MALLOC EINA_ARG_NONNULL(1) EINA_WARN_UNUSED_RESULT;
/**
* @def EINA_ARRAY_ITER_NEXT
@ -98,9 +101,9 @@ EAPI Eina_Accessor * eina_array_accessor_new(const Eina_Array *array)
* @param item The data
* @param iterator The iterator
*
* This macro allow the iteration over @p array in an easy way. It
* This macro allows the iteration over @p array in an easy way. It
* iterates from the first element to the last one. @p index is an
* integer that increase from 0 to the number of elements. @p item is
* integer that increases from 0 to the number of elements. @p item is
* the data of each element of @p array, so it is a pointer to a type
* chosen by the user. @p iterator is of type #Eina_Array_Iterator.
*
@ -126,6 +129,120 @@ EAPI Eina_Accessor * eina_array_accessor_new(const Eina_Array *array)
(index < eina_array_count_get(array)) && ((item = *((iterator)++))); \
++(index))
#ifdef EINA_RWLOCKS_ENABLED
/**
* @def EINA_ARRAY_THREADSAFE_ITER_NEXT
* @brief Macro to iterate over an array easily while mutexing.
*
* @param array The array to iterate over.
* @param index The integer number that is increased while itareting.
* @param item The data
* @param iterator The iterator
* @param code The code in the iterator loop
*
* This macro allows the iteration over @p array in an easy way. It
* iterates from the first element to the last one. @p index is an
* integer that increases from 0 to the number of elements. @p item is
* the data of each element of @p array, so it is a pointer to a type
* chosen by the user. @p iterator is of type #Eina_Array_Iterator.
* @p code is the entire chunk of code which will be in the iterator loop,
* terminated by a semicolon.
*
* This macro can be used for safely freeing the data of an array in a thread,
* like in the following example:
*
* @code
* Eina_Array *array;
* char *item;
* Eina_Array_Iterator iterator;
* unsigned int i;
*
* // array is already filled,
* // its elements are just duplicated strings,
* // EINA_ARRAY_ITER_NEXT will be used to free those strings
*
* EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, item, iterator,
* {
* if (item)
* free(item);
* }
* );
* @endcode
*/
#define EINA_ARRAY_THREADSAFE_ITER_NEXT(array, index, item, iterator, code...) \
if (_eina_array_threadsafety) \
pthread_rwlock_wrlock(&(array)->lock); \
for (index = 0, iterator = (array)->data; \
(index < (array)->count) && ((item = *((iterator)++))); \
++(index)) \
code \
if (_eina_array_threadsafety) \
pthread_rwlock_unlock(&(array)->lock)
#else
#define EINA_ARRAY_THREADSAFE_ITER_NEXT(array, index, item, iterator, code...) \
do \
{ \
for (index = 0, iterator = (array)->data; \
(index < (array)->count) && ((item = *((iterator)++))); \
++(index)) \
code \
} \
while (0)
#endif
#ifdef EINA_RWLOCKS_ENABLED
/**
* @def EINA_ARRAY_THREADSAFE_ITER_RETURN
* @brief Macro to perform a return while using EINA_ARRAY_THREADSAFE_ITER_NEXT
*
* @param array The array being iterated over.
* @param retval The value to be returned
*
* This macro should be used any time the user wishes to perform a return
* statement while using EINA_ARRAY_THREADSAFE_ITER_RETURN to unlock any mutexes
* which may have been locked while iterating. Failure to use this will likely
* result in a deadlock.
*
* example:
*
* @code
* Eina_Array *array;
* char *item;
* Eina_Array_Iterator iterator;
* unsigned int i;
*
* // array is already filled,
* // its elements are just duplicated strings,
* // EINA_ARRAY_ITER_NEXT will be used to free those strings
*
* EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, item, iterator,
* {
* if (item)
* free(item);
* else
* EINA_ARRAY_THREADSAFE_ITER_RETURN(array, NULL);
* }
* );
* @endcode
*/
#define EINA_ARRAY_THREADSAFE_ITER_RETURN(array, retval) \
do \
{ \
if (_eina_array_threadsafety) \
pthread_rwlock_unlock(&(array)->lock); \
return (retval); \
} \
while (0)
#else
#define EINA_ARRAY_THREADSAFE_ITER_RETURN(array, retval) \
return (retval)
#endif
#include "eina_inline_array.x"
/**

View File

@ -19,7 +19,11 @@
#ifndef EINA_INLINE_ARRAY_X_
#define EINA_INLINE_ARRAY_X_
#ifdef EINA_RWLOCKS_ENABLED
# include <pthread.h>
#endif
extern Eina_Bool _eina_array_threadsafety;
/**
* @cond LOCAL
*/
@ -57,10 +61,30 @@ eina_array_push(Eina_Array *array, const void *data)
{
if (!data) return EINA_FALSE;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
if (EINA_UNLIKELY((array->count + 1) > array->total))
if (!eina_array_grow(array)) return EINA_FALSE;
if (!eina_array_grow(array))
{
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return EINA_FALSE;
}
array->data[array->count++] = (void*) data;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return EINA_TRUE;
}
@ -79,8 +103,31 @@ eina_array_push(Eina_Array *array, const void *data)
static inline void *
eina_array_pop(Eina_Array *array)
{
if (array->count <= 0) return NULL;
return array->data[--array->count];
void *ret = NULL;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
if (array->count <= 0)
{
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return NULL;
}
ret = array->data[--array->count];
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return ret;
}
/**
@ -95,26 +142,50 @@ eina_array_pop(Eina_Array *array)
* idx. If it is @c NULL or invalid, the program may crash.
*/
static inline void *
eina_array_data_get(const Eina_Array *array, unsigned int idx)
eina_array_data_get(Eina_Array *array, unsigned int idx)
{
return array->data[idx];
void *ret = NULL;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_rdlock(&array->lock);
#endif
ret = array->data[idx];
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return ret;
}
/**
* @brief Return the data at a given position in an array.
* @brief Set the data at a given position in an array.
*
* @param array The array.
* @param idx The potition of the data to set.
* @param data The data to set.
*
* This function returns the data at the position @p idx in @p
* This function sets the data at the position @p idx in @p
* array. For performance reasons, there is no check of @p array or @p
* idx. If it is @c NULL or invalid, the program may crash.
*/
static inline void
eina_array_data_set(const Eina_Array *array, unsigned int idx, const void *data)
eina_array_data_set(Eina_Array *array, unsigned int idx, const void *data)
{
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
array->data[idx] = (void*) data;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
}
/**
@ -128,9 +199,19 @@ eina_array_data_set(const Eina_Array *array, unsigned int idx, const void *data)
* @c NULL or invalid, the program may crash.
*/
static inline unsigned int
eina_array_count_get(const Eina_Array *array)
eina_array_count_get(Eina_Array *array)
{
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_rdlock(&array->lock);
#endif
return array->count;
#ifdef EINA_RWLOCKS_ENABLED
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
}
/**

View File

@ -164,7 +164,7 @@ eina_module_list_unload(Eina_Array *list) EINA_ARG_NONNULL(1);
EAPI void
eina_module_list_free(Eina_Array *list) EINA_ARG_NONNULL(1);
EAPI Eina_Module *
eina_module_find(const Eina_Array *array, const char *module) EINA_ARG_NONNULL(
eina_module_find(Eina_Array *array, const char *module) EINA_ARG_NONNULL(
1,
2);

View File

@ -129,6 +129,10 @@ void eina_share_common_threads_init(void);
void eina_share_common_threads_shutdown(void);
void eina_log_threads_init(void);
void eina_log_threads_shutdown(void);
#ifdef EINA_RWLOCKS_ENABLE
void eina_array_threadsafety_init(void);
void eina_array_threadsafety_shutdown(void);
#endif
#endif
#endif /* EINA_PRIVATE_H_ */

View File

@ -115,6 +115,10 @@
#include <string.h>
#include <stdio.h>
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
# include <pthread.h>
#endif
#include "eina_config.h"
#include "eina_private.h"
#include "eina_error.h"
@ -165,7 +169,7 @@ struct _Eina_Iterator_Array
{
Eina_Iterator iterator;
const Eina_Array *array;
Eina_Array *array;
unsigned int index;
EINA_MAGIC
@ -175,12 +179,16 @@ typedef struct _Eina_Accessor_Array Eina_Accessor_Array;
struct _Eina_Accessor_Array
{
Eina_Accessor accessor;
const Eina_Array *array;
Eina_Array *array;
EINA_MAGIC
};
static int _eina_array_log_dom = -1;
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
Eina_Bool _eina_array_threadsafety = EINA_FALSE;
#endif
#ifdef ERR
#undef ERR
#endif
@ -191,20 +199,16 @@ static int _eina_array_log_dom = -1;
#endif
#define DBG(...) EINA_LOG_DOM_DBG(_eina_array_log_dom, __VA_ARGS__)
static void eina_array_iterator_free(Eina_Iterator_Array *it)
EINA_ARG_NONNULL(1);
static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it)
EINA_ARG_NONNULL(1);
static void eina_array_iterator_free(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
static Eina_Array *eina_array_iterator_get_container(Eina_Iterator_Array *it) EINA_ARG_NONNULL(1);
static Eina_Bool eina_array_iterator_next(Eina_Iterator_Array *it,
void **data) EINA_ARG_NONNULL(1);
static Eina_Bool eina_array_accessor_get_at(Eina_Accessor_Array *it,
unsigned int idx,
void **data) EINA_ARG_NONNULL(1);
static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it)
EINA_ARG_NONNULL(1);
static void eina_array_accessor_free(Eina_Accessor_Array *it)
EINA_ARG_NONNULL(1);
static Eina_Array *eina_array_accessor_get_container(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
static void eina_array_accessor_free(Eina_Accessor_Array *it) EINA_ARG_NONNULL(1);
static Eina_Bool
eina_array_iterator_next(Eina_Iterator_Array *it, void **data)
@ -347,6 +351,36 @@ eina_array_shutdown(void)
return EINA_TRUE;
}
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
/**
* @brief Enable threadsafe mode in arrays
*
* This function enables threadsafe mode in all arrays.
*
* @warning Once enabled, this CANNOT be disabled.
*/
void
eina_array_threadsafety_init(void)
{
_eina_array_threadsafety = EINA_TRUE;
}
/**
* @brief Disable threadsafe mode in arrays
*
* This function disables threadsafe mode in all arrays.
*/
void
eina_array_threadsafety_shutdown(void)
{
_eina_array_threadsafety = EINA_TRUE;
}
#endif
/*============================================================================*
* API *
*============================================================================*/
@ -422,6 +456,9 @@ eina_array_new(unsigned int step)
array->total = 0;
array->count = 0;
array->step = step;
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
pthread_rwlock_init(&array->lock, NULL);
#endif
DBG("array=%p", array);
@ -434,7 +471,7 @@ eina_array_new(unsigned int step)
* @param array The array to free.
*
* This function frees @p array. It calls first eina_array_flush() then
* free the memory of the pointeur. It does not free the memory
* free the memory of the pointer. It does not free the memory
* allocated for the elements of @p array. To free them, use
* #EINA_ARRAY_ITER_NEXT. For performance reasons, there is no check
* of @p array.
@ -442,11 +479,19 @@ eina_array_new(unsigned int step)
EAPI void
eina_array_free(Eina_Array *array)
{
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
eina_array_flush(array);
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array=%p", array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_destroy(&array->lock);
#endif
MAGIC_FREE(array);
}
@ -464,12 +509,20 @@ EAPI void
eina_array_step_set(Eina_Array *array, unsigned int step)
{
EINA_SAFETY_ON_NULL_RETURN(array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
array->data = NULL;
array->total = 0;
array->count = 0;
array->step = step;
EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
DBG("array=%p, step=%u", array, step);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
}
/**
@ -484,10 +537,18 @@ eina_array_step_set(Eina_Array *array, unsigned int step)
EAPI void
eina_array_clean(Eina_Array *array)
{
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN(array);
EINA_MAGIC_CHECK_ARRAY(array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
array->count = 0;
DBG("array=%p", array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
}
/**
@ -503,8 +564,12 @@ eina_array_clean(Eina_Array *array)
EAPI void
eina_array_flush(Eina_Array *array)
{
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN(array);
EINA_MAGIC_CHECK_ARRAY(array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
DBG("array=%p", array);
array->count = 0;
array->total = 0;
@ -514,6 +579,10 @@ eina_array_flush(Eina_Array *array)
free(array->data);
array->data = NULL;
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
}
/**
@ -548,10 +617,13 @@ eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data,
unsigned int limit;
unsigned int i;
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN_VAL(array, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(keep, EINA_FALSE);
EINA_MAGIC_CHECK_ARRAY(array);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_wrlock(&array->lock);
#endif
DBG("array=%p, keep=%p, gdata=%p", array, keep, gdata);
if (array->total == 0)
@ -626,7 +698,10 @@ eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data,
array->data = tmp;
array->count = total;
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return EINA_TRUE;
}
@ -643,12 +718,12 @@ eina_array_remove(Eina_Array *array, Eina_Bool (*keep)(void *data,
* set. Otherwise, a valid iterator is returned.
*/
EAPI Eina_Iterator *
eina_array_iterator_new(const Eina_Array *array)
eina_array_iterator_new(Eina_Array *array)
{
Eina_Iterator_Array *it;
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
EINA_MAGIC_CHECK_ARRAY(array);
eina_error_set(0);
it = calloc(1, sizeof (Eina_Iterator_Array));
@ -661,6 +736,10 @@ eina_array_iterator_new(const Eina_Array *array)
EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ITERATOR);
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_rdlock(&array->lock);
#endif
it->array = array;
it->iterator.next = FUNC_ITERATOR_NEXT(eina_array_iterator_next);
@ -669,7 +748,10 @@ eina_array_iterator_new(const Eina_Array *array)
it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free);
DBG("array=%p, iterator=%p", array, it);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return &it->iterator;
}
@ -686,12 +768,12 @@ eina_array_iterator_new(const Eina_Array *array)
* set. Otherwise, a valid accessor is returned.
*/
EAPI Eina_Accessor *
eina_array_accessor_new(const Eina_Array *array)
eina_array_accessor_new(Eina_Array *array)
{
Eina_Accessor_Array *it;
EINA_MAGIC_CHECK_ARRAY(array);
EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
EINA_MAGIC_CHECK_ARRAY(array);
eina_error_set(0);
it = calloc(1, sizeof (Eina_Accessor_Array));
@ -704,6 +786,10 @@ eina_array_accessor_new(const Eina_Array *array)
EINA_MAGIC_SET(it, EINA_MAGIC_ARRAY_ACCESSOR);
EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_rdlock(&array->lock);
#endif
it->array = array;
it->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_array_accessor_get_at);
@ -712,7 +798,10 @@ eina_array_accessor_new(const Eina_Array *array)
it->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free);
DBG("array=%p, accessor=%p", array, it);
#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
if (_eina_array_threadsafety)
pthread_rwlock_unlock(&array->lock);
#endif
return &it->accessor;
}

View File

@ -518,8 +518,9 @@ eina_benchmark_free(Eina_Benchmark *bench)
char *tmp;
unsigned int i;
EINA_ARRAY_ITER_NEXT(names, i, tmp, it)
free(tmp);
EINA_ARRAY_THREADSAFE_ITER_NEXT(names, i, tmp, it,
free(tmp);
);
eina_array_free(names);
}

View File

@ -311,6 +311,9 @@ eina_threads_init(void)
eina_share_common_threads_init();
eina_log_threads_init();
#ifdef EFL_RWLOCKS_ENABLE
eina_array_threadsafety_init();
#endif
_threads_activated = EINA_TRUE;
return ret;
@ -349,6 +352,9 @@ eina_threads_shutdown(void)
eina_share_common_threads_shutdown();
eina_log_threads_shutdown();
#ifdef EFL_RWLOCKS_ENABLE
eina_array_threadsafety_shutdown();
#endif
_threads_activated = EINA_FALSE;

View File

@ -623,32 +623,33 @@ EAPI Eina_Array *eina_module_list_get(Eina_Array *array,
* If the element is found return the module else NULL.
*/
EAPI Eina_Module *
eina_module_find(const Eina_Array *array, const char *module)
eina_module_find(Eina_Array *array, const char *module)
{
unsigned int i;
Eina_Array_Iterator iterator;
Eina_Module *m;
EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
{
char *file_m;
char *tmp;
ssize_t len;
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
{
char *file_m;
char *tmp;
ssize_t len;
/* basename() can modify its argument, so we first get a copie */
/* do not use strdupa, as opensolaris does not have it */
len = strlen(eina_module_file_get(m));
tmp = alloca(len + 1);
memcpy(tmp, eina_module_file_get(m), len + 1);
file_m = basename(tmp);
len = strlen(file_m);
len -= sizeof(SHARED_LIB_SUFFIX) - 1;
if (len <= 0)
continue;
/* basename() can modify its argument, so we first get a copie */
/* do not use strdupa, as opensolaris does not have it */
len = strlen(eina_module_file_get(m));
tmp = alloca(len + 1);
memcpy(tmp, eina_module_file_get(m), len + 1);
file_m = basename(tmp);
len = strlen(file_m);
len -= sizeof(SHARED_LIB_SUFFIX) - 1;
if (len <= 0)
continue;
if (!strncmp(module, file_m, len))
return m;
}
if (!strncmp(module, file_m, len))
EINA_ARRAY_THREADSAFE_ITER_RETURN(array, m);
}
);
return NULL;
}
@ -665,8 +666,9 @@ EAPI void eina_module_list_load(Eina_Array *array)
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_load(m);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
eina_module_load(m);
);
}
/**
@ -681,8 +683,9 @@ EAPI void eina_module_list_unload(Eina_Array *array)
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_unload(m);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
eina_module_unload(m);
);
}
/**
@ -697,8 +700,9 @@ EAPI void eina_module_list_free(Eina_Array *array)
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_free(m);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
eina_module_free(m);
);
eina_array_flush(array);
}

View File

@ -96,8 +96,9 @@ _eina_rbtree_iterator_free(Eina_Iterator_Rbtree *it)
Eina_Array_Iterator et;
unsigned int i;
EINA_ARRAY_ITER_NEXT(it->stack, i, item, et)
free(item);
EINA_ARRAY_THREADSAFE_ITER_NEXT(it->stack, i, item, et,
free(item);
);
eina_array_free(it->stack);
free(it);

View File

@ -88,20 +88,23 @@ eina_bench_array_4evas_render_inline(int request)
if (i == 500)
{
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
free(ebo);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, j, ebo, it,
free(ebo);
);
eina_array_clean(array);
}
else if (i % 30 == 0)
eina_array_remove(array, keep, NULL);
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, j, ebo, it,
ebo->keep = rand() < (RAND_MAX / 2) ? ebo->keep : EINA_FALSE;
);
}
EINA_ARRAY_ITER_NEXT(array, j, ebo, it)
free(ebo);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, j, ebo, it,
free(ebo);
);
eina_array_free(array);

View File

@ -344,8 +344,9 @@ eina_bench_lookup_evas(int request)
evas_hash_free(hash);
EINA_ARRAY_ITER_NEXT(array, i, tmp_val, it)
free(tmp_val);
EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, tmp_val, it,
free(tmp_val);
);
eina_array_free(array);
}

View File

@ -53,11 +53,12 @@ START_TEST(eina_array_simple)
fail_if(atoi(tmp) != 200);
free(tmp);
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if((unsigned int)atoi(tmp) != i);
free(tmp);
}
EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
{
fail_if((unsigned int)atoi(tmp) != i);
free(tmp);
}
);
fail_if(i != 200);
@ -92,11 +93,12 @@ START_TEST(eina_array_static)
fail_if(eina_array_data_get(&sea, 10) == NULL);
fail_if(atoi(eina_array_data_get(&sea, 10)) != 10);
EINA_ARRAY_ITER_NEXT(&sea, i, tmp, it)
{
fail_if((unsigned int)atoi(tmp) != i);
free(tmp);
}
EINA_ARRAY_THREADSAFE_ITER_NEXT(&sea, i, tmp, it,
{
fail_if((unsigned int)atoi(tmp) != i);
free(tmp);
}
);
fail_if(i != 200);
@ -152,8 +154,9 @@ START_TEST(eina_array_remove_stuff)
fail_if(eina_array_remove(ea, keep_int, NULL) != EINA_TRUE);
fail_if(eina_array_count_get(ea) != 990);
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
fail_if(*tmp == 0);
EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
fail_if(*tmp == 0);
);
// Remove the last items
for (i = 980; i < 990; ++i)
@ -166,11 +169,12 @@ START_TEST(eina_array_remove_stuff)
// Remove all items
fail_if(eina_array_count_get(ea) != 980);
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if(*tmp == 0);
*tmp = 0;
}
EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
{
fail_if(*tmp == 0);
*tmp = 0;
}
);
eina_array_remove(ea, keep_int, NULL);

View File

@ -57,11 +57,12 @@ START_TEST(eina_benchmark_simple)
ea = eina_benchmark_run(eb);
fail_if(!ea);
EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if(!tmp);
fail_if(unlink(tmp));
}
EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
{
fail_if(!tmp);
fail_if(unlink(tmp));
}
);
fail_if(global_test != 499500);

View File

@ -214,17 +214,18 @@ START_TEST(eina_rbtree_remove)
_eina_rbtree_black_height(&root->node,
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
EINA_ARRAY_ITER_NEXT(ea, i, item, it)
{
root = (Eina_Rbtree_Int *)eina_rbtree_inline_remove(
&root->node,
&item->node,
EINA_RBTREE_CMP_NODE_CB(
eina_rbtree_int_cmp),
NULL);
_eina_rbtree_black_height(&root->node,
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
}
EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, item, it,
{
root = (Eina_Rbtree_Int *)eina_rbtree_inline_remove(
&root->node,
&item->node,
EINA_RBTREE_CMP_NODE_CB(
eina_rbtree_int_cmp),
NULL);
_eina_rbtree_black_height(&root->node,
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
}
);
fail_if(root != NULL);