diff --git a/legacy/eina/src/include/eina_array.h b/legacy/eina/src/include/eina_array.h index 8d66d9e87a..d6407792e4 100644 --- a/legacy/eina/src/include/eina_array.h +++ b/legacy/eina/src/include/eina_array.h @@ -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" /** diff --git a/legacy/eina/src/include/eina_inline_array.x b/legacy/eina/src/include/eina_inline_array.x index 400da2329e..75e499f166 100644 --- a/legacy/eina/src/include/eina_inline_array.x +++ b/legacy/eina/src/include/eina_inline_array.x @@ -19,7 +19,11 @@ #ifndef EINA_INLINE_ARRAY_X_ #define EINA_INLINE_ARRAY_X_ +#ifdef EINA_RWLOCKS_ENABLED +# include +#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 } /** diff --git a/legacy/eina/src/include/eina_module.h b/legacy/eina/src/include/eina_module.h index c5e25bd1e4..113fb69acd 100644 --- a/legacy/eina/src/include/eina_module.h +++ b/legacy/eina/src/include/eina_module.h @@ -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); diff --git a/legacy/eina/src/include/eina_private.h b/legacy/eina/src/include/eina_private.h index 7e8074bc14..f952be903c 100644 --- a/legacy/eina/src/include/eina_private.h +++ b/legacy/eina/src/include/eina_private.h @@ -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_ */ diff --git a/legacy/eina/src/lib/eina_array.c b/legacy/eina/src/lib/eina_array.c index 9d66a6fe2c..ef26a718a0 100644 --- a/legacy/eina/src/lib/eina_array.c +++ b/legacy/eina/src/lib/eina_array.c @@ -115,6 +115,10 @@ #include #include +#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK +# include +#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; } diff --git a/legacy/eina/src/lib/eina_benchmark.c b/legacy/eina/src/lib/eina_benchmark.c index 522719b5c2..47ecd44a09 100644 --- a/legacy/eina/src/lib/eina_benchmark.c +++ b/legacy/eina/src/lib/eina_benchmark.c @@ -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); } diff --git a/legacy/eina/src/lib/eina_main.c b/legacy/eina/src/lib/eina_main.c index 9cb13f7d0a..8c53fc6559 100644 --- a/legacy/eina/src/lib/eina_main.c +++ b/legacy/eina/src/lib/eina_main.c @@ -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; diff --git a/legacy/eina/src/lib/eina_module.c b/legacy/eina/src/lib/eina_module.c index c570d17d3b..75c86e7840 100644 --- a/legacy/eina/src/lib/eina_module.c +++ b/legacy/eina/src/lib/eina_module.c @@ -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); } diff --git a/legacy/eina/src/lib/eina_rbtree.c b/legacy/eina/src/lib/eina_rbtree.c index 88a471c6df..be0d9772c5 100644 --- a/legacy/eina/src/lib/eina_rbtree.c +++ b/legacy/eina/src/lib/eina_rbtree.c @@ -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); diff --git a/legacy/eina/src/tests/eina_bench_array.c b/legacy/eina/src/tests/eina_bench_array.c index cf6b8057a8..50d1b04079 100644 --- a/legacy/eina/src/tests/eina_bench_array.c +++ b/legacy/eina/src/tests/eina_bench_array.c @@ -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); diff --git a/legacy/eina/src/tests/eina_bench_hash.c b/legacy/eina/src/tests/eina_bench_hash.c index 93bb69e993..a615a1504d 100644 --- a/legacy/eina/src/tests/eina_bench_hash.c +++ b/legacy/eina/src/tests/eina_bench_hash.c @@ -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); } diff --git a/legacy/eina/src/tests/eina_test_array.c b/legacy/eina/src/tests/eina_test_array.c index 2b90261248..c5d118db3f 100644 --- a/legacy/eina/src/tests/eina_test_array.c +++ b/legacy/eina/src/tests/eina_test_array.c @@ -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); diff --git a/legacy/eina/src/tests/eina_test_benchmark.c b/legacy/eina/src/tests/eina_test_benchmark.c index 04362c2880..213bc7c6a9 100644 --- a/legacy/eina/src/tests/eina_test_benchmark.c +++ b/legacy/eina/src/tests/eina_test_benchmark.c @@ -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); diff --git a/legacy/eina/src/tests/eina_test_rbtree.c b/legacy/eina/src/tests/eina_test_rbtree.c index ad3f63e664..dcf00fbdf7 100644 --- a/legacy/eina/src/tests/eina_test_rbtree.c +++ b/legacy/eina/src/tests/eina_test_rbtree.c @@ -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);