void **data);
typedef void *(*Eina_Accessor_Get_Container_Callback)(Eina_Accessor *it);
typedef void (*Eina_Accessor_Free_Callback)(Eina_Accessor *it);
+typedef Eina_Bool (*Eina_Accessor_Lock_Callback)(Eina_Accessor *it);
struct _Eina_Accessor
{
EINA_WARN_UNUSED_RESULT;
Eina_Accessor_Free_Callback free EINA_ARG_NONNULL(1);
+ Eina_Accessor_Lock_Callback lock EINA_WARN_UNUSED_RESULT;
+ Eina_Accessor_Lock_Callback unlock EINA_WARN_UNUSED_RESULT;
+
#define EINA_MAGIC_ACCESSOR 0x98761232
EINA_MAGIC
};
Eina_Accessor_Get_Container_Callback) \
Function)
#define FUNC_ACCESSOR_FREE(Function) ((Eina_Accessor_Free_Callback)Function)
-
+#define FUNC_ACCESSOR_LOCK(Function) ((Eina_Accessor_Lock_Callback)Function)
EAPI void eina_accessor_free (Eina_Accessor *accessor)
EINA_ARG_NONNULL(1);
EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void eina_accessor_over (Eina_Accessor *accessor,
- Eina_Each cb,
+ Eina_Each_Cb cb,
unsigned int start,
unsigned int end,
const void *fdata)
EINA_ARG_NONNULL(1, 2);
+EAPI Eina_Bool eina_accessor_lock(Eina_Accessor *accessor) EINA_ARG_NONNULL(1);
+EAPI Eina_Bool eina_accessor_unlock(Eina_Accessor *accessor) EINA_ARG_NONNULL(1);
+
/**
* @def EINA_ACCESSOR_FOREACH
* @brief Macro to iterate over all elements easily.
unsigned int step; /**< How much must we grow the vector when it is full */
#ifdef EINA_RWLOCKS_ENABLED
pthread_rwlock_t lock;
- int lockcount;
Eina_Bool threadsafe:1;
#endif
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;
-#ifdef EINA_RWLOCKS_ENABLED
-static inline Eina_Bool
-eina_array_rdlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- if (array->threadsafe)
- {
- if (!array->lockcount++)
- {
- int ret;
-
- ret = pthread_rwlock_rdlock(&array->lock);
- if ((ret != 0) && (ret != EDEADLK))
- return EINA_FALSE;
- }
- }
- return EINA_TRUE;
-}
-
-static inline Eina_Bool
-eina_array_wrlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- if (array->threadsafe)
- {
- if (!array->lockcount++)
- {
- int ret;
+static inline Eina_Bool eina_array_rdlock(const Eina_Array *array);
+static inline Eina_Bool eina_array_wrlock(Eina_Array *array);
+static inline Eina_Bool eina_array_unlock(const Eina_Array *array);
- ret = pthread_rwlock_wrlock(&array->lock);
- if ((ret != 0) && (ret != EDEADLK))
- return EINA_FALSE;
- }
- }
- return EINA_TRUE;
-}
-static inline Eina_Bool
-eina_array_unlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- if ((array->threadsafe) && (!(--array->lockcount)))
- if (pthread_rwlock_unlock(&array->lock))
- return EINA_FALSE;
- return EINA_TRUE;
-}
-#else
-static inline Eina_Bool
-eina_array_rdlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- return EINA_TRUE;
-}
-
-static inline Eina_Bool
-eina_array_wrlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- return EINA_TRUE;
-}
-
-static inline Eina_Bool
-eina_array_unlock(Eina_Array *array)
-{
- if (!array) return EINA_FALSE;
- return EINA_TRUE;
-}
-#endif
+static inline Eina_Bool eina_array_foreach(Eina_Array *array, Eina_Each_Cb cb, void *data);
/**
* @def EINA_ARRAY_ITER_NEXT
(index < eina_array_count_get(array)) && ((item = *((iterator)++))); \
++(index))
-/**
- * @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...) \
-do \
- { \
- if (eina_array_wrlock((Eina_Array*)array)) \
- { \
- for (index = 0, iterator = (array)->data; \
- (index < (array)->count) && ((item = *((iterator)++))); \
- ++(index)) \
- code \
- eina_array_unlock((Eina_Array*)array); \
- } \
- } while (0)
-
-
-/**
- * @def EINA_ARRAY_THREADSAFE_ITER_ESCAPE
- * @brief Macro to break a loop while using EINA_ARRAY_THREADSAFE_ITER_NEXT
- *
- * @param array The array being iterated over.
- * @param esc The code to "escape" the loop with
- *
- * This macro should be used any time the user wishes to leave the loop
- * while using EINA_ARRAY_THREADSAFE_ITER_NEXT. It will 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_ESCAPE(array, return NULL;);
- * }
- * );
- * @endcode
- */
-#define EINA_ARRAY_THREADSAFE_ITER_ESCAPE(array, esc...) \
-do \
- { \
- eina_array_unlock((Eina_Array*)array); \
- esc \
- } \
-while (0)
-
#include "eina_inline_array.x"
/**
#ifndef EINA_INLINE_ARRAY_X_
#define EINA_INLINE_ARRAY_X_
+#ifdef EINA_RWLOCKS_ENABLED
+# include <pthread.h>
+#endif
+
/**
* @cond LOCAL
*/
* #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, #EINA_TRUE is
* returned.
*/
+#include <stdio.h>
+
static inline Eina_Bool
eina_array_push(Eina_Array *array, const void *data)
{
if (!data) return EINA_FALSE;
- if (!eina_array_wrlock(array))
+ if (EINA_UNLIKELY(!eina_array_wrlock(array)))
return EINA_FALSE;
if (EINA_UNLIKELY((array->count + 1) > array->total))
eina_array_pop(Eina_Array *array)
{
void *ret = NULL;
-
- if (!eina_array_wrlock(array))
+
+ if (EINA_UNLIKELY(!eina_array_wrlock(array)))
return NULL;
if (array->count <= 0)
- {
- eina_array_unlock(array);
- return NULL;
- }
+ goto on_empty;
+
ret = array->data[--array->count];
-
+
+ on_empty:
eina_array_unlock(array);
return ret;
return array->count;
}
+#ifdef EINA_RWLOCKS_ENABLED
+static inline Eina_Bool
+eina_array_rdlock(const Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ if (array->threadsafe)
+ {
+ int ret;
+
+ ret = pthread_rwlock_rdlock(&((Eina_Array*) array)->lock);
+ if ((ret != 0) && (ret != EDEADLK))
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+eina_array_wrlock(Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ if (array->threadsafe)
+ {
+ int ret;
+
+ ret = pthread_rwlock_wrlock(&array->lock);
+ if ((ret != 0) && (ret != EDEADLK))
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+eina_array_unlock(const Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ if (array->threadsafe)
+ if (pthread_rwlock_unlock(&((Eina_Array*) array)->lock))
+ return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+#else
+
+static inline Eina_Bool
+eina_array_rdlock(const Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+eina_array_wrlock(Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+eina_array_unlock(const Eina_Array *array)
+{
+ if (!array) return EINA_FALSE;
+ return EINA_TRUE;
+}
+#endif
+
+/**
+ * @brief Provide a safe way to iterate over an array
+ *
+ * @param array The array to iterate over.
+ * @param cb The callback to call for each item.
+ * @param fdata The user data to pass to the callback.
+ * @return EINA_TRUE if it successfully iterate all items of the array.
+ *
+ * This function provide a safe way to iterate over an array. If
+ * the array was created with @p eina_array_threadsafe_new, it will
+ * be correctly locked and unlocked. @p cb should return EINA_TRUE
+ * as long as you want the function to continue iterating, by
+ * returning EINA_FALSE it will stop and return EINA_FALSE as a
+ * result.
+ */
+static inline Eina_Bool
+eina_array_foreach(Eina_Array *array, Eina_Each_Cb cb, void *fdata)
+{
+ void *data;
+ Eina_Array_Iterator iterator;
+ unsigned int i;
+ Eina_Bool ret = EINA_TRUE;
+
+ if (EINA_UNLIKELY(!eina_array_wrlock(array)))
+ return EINA_FALSE;
+
+ EINA_ARRAY_ITER_NEXT(array, i, data, iterator)
+ if (cb(array, data, fdata) != EINA_TRUE)
+ {
+ ret = EINA_FALSE;
+ break;
+ }
+
+ eina_array_unlock(array);
+
+ return ret;
+}
+
/**
* @}
*/
typedef Eina_Bool (*Eina_Iterator_Next_Callback)(Eina_Iterator *it, void **data);
typedef void *(*Eina_Iterator_Get_Container_Callback)(Eina_Iterator *it);
typedef void (*Eina_Iterator_Free_Callback)(Eina_Iterator *it);
+typedef Eina_Bool (*Eina_Iterator_Lock_Callback)(Eina_Iterator *it);
struct _Eina_Iterator
{
EINA_WARN_UNUSED_RESULT;
Eina_Iterator_Free_Callback free EINA_ARG_NONNULL(1);
+ Eina_Iterator_Lock_Callback lock EINA_WARN_UNUSED_RESULT;
+ Eina_Iterator_Lock_Callback unlock EINA_WARN_UNUSED_RESULT;
+
#define EINA_MAGIC_ITERATOR 0x98761233
EINA_MAGIC
};
Eina_Iterator_Get_Container_Callback) \
Function)
#define FUNC_ITERATOR_FREE(Function) ((Eina_Iterator_Free_Callback)Function)
+#define FUNC_ITERATOR_LOCK(Function) ((Eina_Iterator_Lock_Callback)Function)
EAPI void eina_iterator_free (Eina_Iterator *iterator)
EINA_ARG_NONNULL(1);
EINA_WARN_UNUSED_RESULT;
EAPI void eina_iterator_foreach (Eina_Iterator *iterator,
- Eina_Each callback,
+ Eina_Each_Cb callback,
const void *fdata)
EINA_ARG_NONNULL(1, 2);
+EAPI Eina_Bool eina_iterator_lock(Eina_Iterator *iterator) EINA_ARG_NONNULL(1);
+EAPI Eina_Bool eina_iterator_unlock(Eina_Iterator *iterator) EINA_ARG_NONNULL(1);
+
/**
* @def EINA_ITERATOR_FOREACH
* @brief Macro to iterate over all elements easily.
*/
#define EINA_COMPARE_CB(function) ((Eina_Compare_Cb)function)
-typedef Eina_Bool (*Eina_Each)(const void *container,
- void *data,
- void *fdata);
+typedef Eina_Bool (*Eina_Each_Cb)(const void *container,
+ void *data,
+ void *fdata);
/**
- * @def EINA_EACH
+ * @def EINA_EACH_CB
* Macro to cast to Eina_Each.
*/
-#define EINA_EACH(Function) ((Eina_Each)Function)
+#define EINA_EACH_CB(Function) ((Eina_Each_Cb)Function)
/**
* @typedef Eina_Free_Cb
*/
EAPI void
eina_accessor_over(Eina_Accessor *accessor,
- Eina_Each cb,
+ Eina_Each_Cb cb,
unsigned int start,
unsigned int end,
const void *fdata)
EINA_SAFETY_ON_NULL_RETURN(cb);
EINA_SAFETY_ON_FALSE_RETURN(start < end);
+ if (!eina_accessor_lock(accessor))
+ return ;
+
container = accessor->get_container(accessor);
for (i = start; i < end && accessor->get_at(accessor, i, &data) == EINA_TRUE;
++i)
if (cb(container, data, (void *)fdata) != EINA_TRUE)
- return;
+ goto on_exit;
+
+ on_exit:
+ (void) eina_accessor_unlock(accessor);
+}
+
+/**
+ * @brief Lock the container of the accessor.
+ *
+ * @param accessor The accessor.
+ * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
+ *
+ * If the container of the @p accessor permit it, it will be locked.
+ * If @p accessor is @c NULL or if a problem occured, #EINA_FALSE is
+ * returned, otherwise #EINA_TRUE is returned. If the container
+ * is not lockable, it will return EINA_TRUE.
+ */
+EAPI Eina_Bool
+eina_accessor_lock(Eina_Accessor *accessor)
+{
+ EINA_MAGIC_CHECK_ACCESSOR(accessor);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
+ if (accessor->lock)
+ return accessor->lock(accessor);
+ return EINA_TRUE;
+}
+
+/**
+ * @brief Unlock the container of the accessor.
+ *
+ * @param accessor The accessor.
+ * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
+ *
+ * If the container of the @p accessor permit it and was previously
+ * locked, it will be unlocked. If @p accessor is @c NULL or if a
+ * problem occured, #EINA_FALSE is returned, otherwise #EINA_TRUE
+ * is returned. If the container is not lockable, it will return
+ * EINA_TRUE.
+ */
+EAPI Eina_Bool
+eina_accessor_unlock(Eina_Accessor *accessor)
+{
+ EINA_MAGIC_CHECK_ACCESSOR(accessor);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(accessor, EINA_FALSE);
+
+ if (accessor->unlock)
+ return accessor->unlock(accessor);
+ return EINA_TRUE;
}
/**
#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"
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
}
static Eina_Bool
+eina_array_iterator_lock(Eina_Iterator_Array *it)
+{
+ EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
+ return eina_array_wrlock((Eina_Array *) it->array);
+}
+
+static Eina_Bool
+eina_array_iterator_unlock(Eina_Iterator_Array *it)
+{
+ EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
+ return eina_array_unlock(it->array);
+}
+
+static Eina_Bool
eina_array_accessor_get_at(Eina_Accessor_Array *it,
unsigned int idx,
void **data)
MAGIC_FREE(it);
}
+static Eina_Bool
+eina_array_accessor_lock(Eina_Accessor_Array *it)
+{
+ EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
+ return eina_array_wrlock((Eina_Array *) it->array);
+}
+
+static Eina_Bool
+eina_array_accessor_unlock(Eina_Accessor_Array *it)
+{
+ EINA_MAGIC_CHECK_ARRAY_ITERATOR(it, EINA_FALSE);
+ return eina_array_unlock(it->array);
+}
+
EAPI Eina_Bool
eina_array_grow(Eina_Array *array)
{
{
Eina_Array *array;
- eina_error_set(0);
+ eina_error_set(0);
array = malloc(sizeof (Eina_Array));
if (!array)
{
array->total = 0;
array->count = 0;
array->step = step;
-#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
+#ifdef EINA_RWLOCKS_ENABLED
array->threadsafe = EINA_FALSE;
- array->lockcount = 0;
#endif
- DBG("array=%p", array);
-
return array;
}
* #EINA_ERROR_OUT_OF_MEMORY.
*/
EAPI Eina_Array *
-eina_array_threadsafe_new(__UNUSED__ unsigned int step)
+eina_array_threadsafe_new(unsigned int step)
{
-#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
+#ifdef EINA_RWLOCKS_ENABLED
Eina_Array *array;
eina_error_set(0);
pthread_rwlock_init(&array->lock, NULL);
array->threadsafe = EINA_TRUE;
-
- DBG("array=%p", array);
-
return array;
#else
+ (void) step;
+
return NULL;
#endif
}
if (!eina_array_wrlock(array))
return;
EINA_MAGIC_CHECK_ARRAY(array);
- DBG("array=%p", array);
-#ifdef EFL_HAVE_POSIX_THREADS_RWLOCK
+#ifdef EINA_RWLOCKS_ENABLED
if (array->threadsafe)
pthread_rwlock_destroy(&array->lock);
#endif
*
* This function sets the step of @p array to @p step. For performance
* reasons, there is no check of @p array. If it is @c NULL or
- * invalid, the program may crash.
+ * invalid, the program may crash. This function should be called when
+ * the array is not initialized.
*/
EAPI void
eina_array_step_set(Eina_Array *array, unsigned int step)
{
EINA_SAFETY_ON_NULL_RETURN(array);
- if (!eina_array_wrlock(array))
- return;
array->data = NULL;
array->total = 0;
array->count = 0;
array->step = step;
+#ifdef EINA_RWLOCKS_ENABLED
+ array->threadsafe = EINA_FALSE;
+#endif
EINA_MAGIC_SET(array, EINA_MAGIC_ARRAY);
- DBG("array=%p, step=%u", array, step);
- eina_array_unlock(array);
}
/**
eina_array_clean(Eina_Array *array)
{
EINA_SAFETY_ON_NULL_RETURN(array);
+ EINA_MAGIC_CHECK_ARRAY(array);
+
if (!eina_array_wrlock(array))
return;
- EINA_MAGIC_CHECK_ARRAY(array);
+
array->count = 0;
- DBG("array=%p", array);
eina_array_unlock(array);
}
eina_array_flush(Eina_Array *array)
{
EINA_SAFETY_ON_NULL_RETURN(array);
+ EINA_MAGIC_CHECK_ARRAY(array);
if (!eina_array_wrlock(array))
return;
- EINA_MAGIC_CHECK_ARRAY(array);
- DBG("array=%p", array);
array->count = 0;
array->total = 0;
return EINA_FALSE;
EINA_MAGIC_CHECK_ARRAY(array);
- DBG("array=%p, keep=%p, gdata=%p", array, keep, gdata);
-
if (array->total == 0)
return EINA_TRUE;
EINA_SAFETY_ON_NULL_RETURN_VAL(array, NULL);
EINA_MAGIC_CHECK_ARRAY(array);
- eina_error_set(0);
+ eina_error_set(0);
it = calloc(1, sizeof (Eina_Iterator_Array));
if (!it)
{
eina_array_iterator_get_container);
it->iterator.free = FUNC_ITERATOR_FREE(eina_array_iterator_free);
- DBG("array=%p, iterator=%p", array, it);
+ if (array->threadsafe)
+ {
+ it->iterator.lock = FUNC_ITERATOR_LOCK(eina_array_iterator_lock);
+ it->iterator.unlock = FUNC_ITERATOR_LOCK(eina_array_iterator_unlock);
+ }
return &it->iterator;
}
eina_array_accessor_get_container);
it->accessor.free = FUNC_ACCESSOR_FREE(eina_array_accessor_free);
- DBG("array=%p, accessor=%p", array, it);
+ if (array->threadsafe)
+ {
+ it->accessor.lock = FUNC_ACCESSOR_LOCK(eina_array_accessor_lock);
+ it->accessor.unlock = FUNC_ACCESSOR_LOCK(eina_array_accessor_unlock);
+ }
return &it->accessor;
}
char *tmp;
unsigned int i;
- EINA_ARRAY_THREADSAFE_ITER_NEXT(names, i, tmp, it,
- free(tmp);
- );
+ EINA_ARRAY_ITER_NEXT(names, i, tmp, it)
+ free(tmp);
eina_array_free(names);
}
continue;
it = eina_rbtree_iterator_prefix(hash->buckets[hash_num]);
- eina_iterator_foreach(it, EINA_EACH(_eina_hash_rbtree_each), &each);
+ eina_iterator_foreach(it, EINA_EACH_CB(_eina_hash_rbtree_each), &each);
eina_iterator_free(it);
if (each.el)
if (!it)
return;
- eina_iterator_foreach(it, EINA_EACH(_eina_foreach_cb), &foreach);
+ eina_iterator_foreach(it, EINA_EACH_CB(_eina_foreach_cb), &foreach);
eina_iterator_free(it);
}
*/
EAPI void
eina_iterator_foreach(Eina_Iterator *iterator,
- Eina_Each cb,
+ Eina_Each_Cb cb,
const void *fdata)
{
const void *container;
EINA_SAFETY_ON_NULL_RETURN(iterator->next);
EINA_SAFETY_ON_NULL_RETURN(cb);
+ if (!eina_iterator_lock(iterator)) return ;
+
container = iterator->get_container(iterator);
while (iterator->next(iterator, &data) == EINA_TRUE) {
if (cb(container, data, (void *)fdata) != EINA_TRUE)
- return;
+ goto on_exit;
}
+
+ on_exit:
+ (void) eina_iterator_unlock(iterator);
+}
+
+/**
+ * @brief Lock the container of the iterator.
+ *
+ * @param iterator The iterator.
+ * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
+ *
+ * If the container of the @p iterator permit it, it will be locked.
+ * If @p iterator is @c NULL or if a problem occured, #EINA_FALSE is
+ * returned, otherwise #EINA_TRUE is returned. If the container
+ * is not lockable, it will return EINA_TRUE.
+ */
+EAPI Eina_Bool
+eina_iterator_lock(Eina_Iterator *iterator)
+{
+ EINA_MAGIC_CHECK_ITERATOR(iterator);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE);
+
+ if (iterator->lock)
+ return iterator->lock(iterator);
+ return EINA_TRUE;
+}
+
+/**
+ * @brief Unlock the container of the iterator.
+ *
+ * @param iterator The iterator.
+ * @return #EINA_TRUE on success, #EINA_FALSE otherwise.
+ *
+ * If the container of the @p iterator permit it and was previously
+ * locked, it will be unlocked. If @p iterator is @c NULL or if a
+ * problem occured, #EINA_FALSE is returned, otherwise #EINA_TRUE
+ * is returned. If the container is not lockable, it will return
+ * EINA_TRUE.
+ */
+EAPI Eina_Bool
+eina_iterator_unlock(Eina_Iterator *iterator)
+{
+ EINA_MAGIC_CHECK_ITERATOR(iterator);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(iterator, EINA_FALSE);
+
+ if (iterator->unlock)
+ return iterator->unlock(iterator);
+ return EINA_TRUE;
}
/**
Eina_Array_Iterator iterator;
Eina_Module *m;
- EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
+ EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
{
char *file_m;
char *tmp;
continue;
if (!strncmp(module, file_m, len))
- EINA_ARRAY_THREADSAFE_ITER_ESCAPE(array, return m;);
+ return m;;
}
- );
return NULL;
}
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
+ EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_load(m);
- );
}
/**
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
+ EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_unload(m);
- );
}
/**
EINA_SAFETY_ON_NULL_RETURN(array);
DBG("array %p, count %u", array, array->count);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(array, i, m, iterator,
+ EINA_ARRAY_ITER_NEXT(array, i, m, iterator)
eina_module_free(m);
- );
eina_array_flush(array);
}
Eina_Array_Iterator et;
unsigned int i;
- EINA_ARRAY_THREADSAFE_ITER_NEXT(it->stack, i, item, et,
+ EINA_ARRAY_ITER_NEXT(it->stack, i, item, et)
free(item);
- );
eina_array_free(it->stack);
free(it);
// sizeof(Eina_Share_Common_Head), sizeof(Eina_Share_Common_Node));
it = eina_rbtree_iterator_prefix(
(Eina_Rbtree *)share->share->buckets[i]);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_array_check), &di);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &di);
eina_iterator_free(it);
}
if (additional_dump)
if (i == 500)
{
it = eina_array_iterator_new(array);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_free), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_free), NULL);
eina_iterator_free(it);
eina_array_clean(array);
eina_array_remove(array, keep, NULL);
it = eina_array_iterator_new(array);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_rand), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
eina_iterator_free(it);
}
it = eina_array_iterator_new(array);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_free), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_free), NULL);
eina_iterator_free(it);
eina_array_free(array);
}
it = eina_list_iterator_new(list);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_rand), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
eina_iterator_free(it);
}
}
it = eina_inlist_iterator_new(head);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_ebo_rand), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_ebo_rand), NULL);
eina_iterator_free(it);
}
fail_if(*tmp != 100);
i = 50;
- eina_accessor_over(it, EINA_EACH(eina_accessor_check), 50, 100, &i);
+ eina_accessor_over(it, EINA_EACH_CB(eina_accessor_check), 50, 100, &i);
fail_if(i != 99);
fail_if(eina_accessor_container_get(it) != ea);
fail_if(!it);
fail_if(eina_accessor_container_get(it) != lst);
- eina_accessor_over(it, EINA_EACH(eina_accessor_inlist_data_check), 2, 4, &i);
+ eina_accessor_over(it, EINA_EACH_CB(eina_accessor_inlist_data_check), 2, 4, &i);
fail_if(eina_accessor_data_get(it, 5, (void **)&tmp) != EINA_TRUE);
fail_if(eina_accessor_data_get(it, 3, (void **)&tmp) != EINA_TRUE);
it = eina_list_accessor_new(list);
fail_if(!it);
- eina_accessor_over(it, EINA_EACH(eina_iterator_list_data_check), 2, 4, &i);
+ eina_accessor_over(it, EINA_EACH_CB(eina_iterator_list_data_check), 2, 4, &i);
fail_if(eina_accessor_data_get(it, 5, (void **)&j) != EINA_TRUE);
fail_if(*j != 1);
eina_init();
- ea = eina_array_threadsafe_new(11);
+ ea = eina_array_new(11);
fail_if(!ea);
for (i = 0; i < 201; ++i)
fail_if(atoi(tmp) != 200);
free(tmp);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
- fail_if((unsigned int)atoi(tmp) != i);
- free(tmp);
+ fail_if((unsigned int)atoi(tmp) != i);
+ free(tmp);
+ }
+
+ fail_if(i != 200);
+
+ eina_array_clean(ea);
+ eina_array_flush(ea);
+ eina_array_free(ea);
+
+ eina_shutdown();
+}
+END_TEST
+
+static Eina_Bool
+_eina_array_clean(Eina_Array *ea, char *tmp, unsigned int *i)
+{
+ fail_if(!ea);
+ fail_if((unsigned int)atoi(tmp) != *i);
+ free(tmp);
+
+ (*i)++;
+
+ return EINA_TRUE;
+}
+
+START_TEST(eina_array_threadsafe)
+{
+ Eina_Array *ea;
+ char *tmp;
+ unsigned int i;
+
+ eina_init();
+
+ ea = eina_array_threadsafe_new(11);
+ fail_if(!ea);
+
+ for (i = 0; i < 201; ++i)
+ {
+ tmp = malloc(sizeof(char) * 10);
+ fail_if(!tmp);
+ eina_convert_itoa(i, tmp);
+
+ eina_array_push(ea, tmp);
}
- );
+
+ fail_if(eina_array_data_get(ea, 10) == NULL);
+ fail_if(atoi(eina_array_data_get(ea, 10)) != 10);
+ tmp = eina_array_pop(ea);
+ fail_if(tmp == NULL);
+ fail_if(atoi(tmp) != 200);
+ free(tmp);
+
+ i = 0;
+ eina_array_foreach(ea, EINA_EACH_CB(_eina_array_clean), &i);
fail_if(i != 200);
fail_if(eina_array_data_get(&sea, 10) == NULL);
fail_if(atoi(eina_array_data_get(&sea, 10)) != 10);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(&sea, i, tmp, it,
+ EINA_ARRAY_ITER_NEXT(&sea, i, tmp, it)
{
- fail_if((unsigned int)atoi(tmp) != i);
+ fail_if((unsigned int)atoi(tmp) != i);
free(tmp);
}
- );
fail_if(i != 200);
fail_if(!tmp);
*tmp = 0;
}
- fail_if(eina_array_remove(ea, keep_int, NULL) != EINA_TRUE);
+ fail_if(eina_array_remove(ea, keep_int, NULL) != EINA_TRUE);
- fail_if(eina_array_count_get(ea) != 990);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
- fail_if(*tmp == 0);
- );
+ fail_if(eina_array_count_get(ea) != 990);
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
+ fail_if(*tmp == 0);
// Remove the last items
for (i = 980; i < 990; ++i)
// Remove all items
fail_if(eina_array_count_get(ea) != 980);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if(*tmp == 0);
*tmp = 0;
}
- );
eina_array_remove(ea, keep_int, NULL);
eina_test_array(TCase *tc)
{
tcase_add_test(tc, eina_array_simple);
+ tcase_add_test(tc, eina_array_threadsafe);
tcase_add_test(tc, eina_array_static);
tcase_add_test(tc, eina_array_remove_stuff);
}
fail_if(!eb);
eina_benchmark_register(eb, "specimens_check",
- EINA_BENCHMARK(
- _eina_benchmark_specimens), 1000, 1100, 100);
+ EINA_BENCHMARK(_eina_benchmark_specimens),
+ 1000, 1100, 100);
ea = eina_benchmark_run(eb);
fail_if(!ea);
- EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, tmp, it,
+ EINA_ARRAY_ITER_NEXT(ea, i, tmp, it)
{
fail_if(!tmp);
fail_if(unlink(tmp));
}
- );
- fail_if(global_test != 499500);
+ fail_if(global_test != 499500);
- eina_benchmark_free(eb);
+ eina_benchmark_free(eb);
}
END_TEST
fail_if(!it);
i = -1;
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_array_check), &i);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_array_check), &i);
fail_if(i != 199);
fail_if(eina_iterator_container_get(it) != ea);
fail_if(eina_hash_add(hash, "6", &array[4]) != EINA_TRUE);
it = eina_hash_iterator_key_new(hash);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_key_check), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_key_check), NULL);
eina_iterator_free(it);
it = eina_hash_iterator_data_new(hash);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_data_check), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_data_check), NULL);
eina_iterator_free(it);
it = eina_hash_iterator_tuple_new(hash);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_hash_tuple_check), NULL);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_hash_tuple_check), NULL);
eina_iterator_free(it);
eina_hash_free(hash);
it = eina_inlist_iterator_new(lst);
fail_if(!it);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_inlist_data_check), &i);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_inlist_data_check), &i);
eina_iterator_free(it);
fail_if(i != 5);
it = eina_list_iterator_new(list);
fail_if(!it);
- eina_iterator_foreach(it, EINA_EACH(eina_iterator_list_data_check), &i);
+ eina_iterator_foreach(it, EINA_EACH_CB(eina_iterator_list_data_check), &i);
eina_iterator_free(it);
}
END_TEST
Eina_Iterator *it;
int i;
- root = eina_rbtree_inline_insert(NULL, _eina_rbtree_int_new(
- 10),
- EINA_RBTREE_CMP_NODE_CB(
- eina_rbtree_int_cmp), NULL);
+ root = eina_rbtree_inline_insert(NULL,
+ _eina_rbtree_int_new(10),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
fail_if(!root);
- root = eina_rbtree_inline_insert(root, _eina_rbtree_int_new(
- 1337),
- EINA_RBTREE_CMP_NODE_CB(
- eina_rbtree_int_cmp), NULL);
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(1337),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
fail_if(!root);
- root = eina_rbtree_inline_insert(root, _eina_rbtree_int_new(
- 27),
- EINA_RBTREE_CMP_NODE_CB(
- eina_rbtree_int_cmp), NULL);
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(27),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
fail_if(!root);
- root = eina_rbtree_inline_insert(root, _eina_rbtree_int_new(
- 69),
- EINA_RBTREE_CMP_NODE_CB(
- eina_rbtree_int_cmp), NULL);
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(69),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
fail_if(!root);
- root = eina_rbtree_inline_insert(root, _eina_rbtree_int_new(
- 42),
- EINA_RBTREE_CMP_NODE_CB(
- eina_rbtree_int_cmp), NULL);
+ root = eina_rbtree_inline_insert(root,
+ _eina_rbtree_int_new(42),
+ EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp),
+ NULL);
fail_if(!root);
i = 0;
it = eina_rbtree_iterator_prefix(root);
fail_if(!it);
- eina_iterator_foreach(it, EINA_EACH(
- eina_iterator_rbtree_data_check_prefix), &i);
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_prefix),
+ &i);
eina_iterator_free(it);
/* This will return the item sorted. */
it = eina_rbtree_iterator_infix(root);
fail_if(!it);
- eina_iterator_foreach(it, EINA_EACH(
- eina_iterator_rbtree_data_check_sorted), &i);
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_sorted),
+ &i);
eina_iterator_free(it);
i = 0;
it = eina_rbtree_iterator_postfix(root);
fail_if(!it);
- eina_iterator_foreach(it, EINA_EACH(
- eina_iterator_rbtree_data_check_postfix), &i);
+ eina_iterator_foreach(it,
+ EINA_EACH_CB(eina_iterator_rbtree_data_check_postfix),
+ &i);
eina_iterator_free(it);
}
END_TEST
_eina_rbtree_black_height(&root->node,
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
- EINA_ARRAY_THREADSAFE_ITER_NEXT(ea, i, item, it,
+ EINA_ARRAY_ITER_NEXT(ea, i, item, it)
{
root = (Eina_Rbtree_Int *)eina_rbtree_inline_remove(
&root->node,
_eina_rbtree_black_height(&root->node,
EINA_RBTREE_CMP_NODE_CB(eina_rbtree_int_cmp));
}
- );
fail_if(root != NULL);