* Add eina_hash_free_cb_set to change the free callback during the
life of an Eina_Hash.
+
+2011-06-23 Cedric Bail
+
+ * Add Eina_LockRW.
#endif
typedef struct _Eina_Lock Eina_Lock;
+typedef struct _Eina_RWLock Eina_RWLock;
typedef struct _Eina_Condition Eina_Condition;
struct _Eina_Lock
pthread_cond_t condition;
};
+struct _Eina_RWLock
+{
+ pthread_rwlock_t mutex;
+#ifdef EINA_HAVE_DEBUG_THREADS
+ pthread_t lock_thread_wid;
+#endif
+};
+
EAPI extern Eina_Bool _eina_threads_activated;
#ifdef EINA_HAVE_DEBUG_THREADS
return pthread_cond_signal(&(cond->condition)) == 0 ? EINA_TRUE : EINA_FALSE;
}
+static inline Eina_Bool
+eina_rwlock_new(Eina_RWLock *mutex)
+{
+#ifdef EINA_HAVE_DEBUG_THREADS
+ assert(pthread_equal(_eina_main_loop, pthread_self()));
+#endif
+
+ if (pthread_rwlock_init(&(mutex->mutex), NULL) != 0)
+ return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static inline void
+eina_rwlock_free(Eina_RWLock *mutex)
+{
+#ifdef EINA_HAVE_DEBUG_THREADS
+ assert(pthread_equal(_eina_main_loop, pthread_self()));
+#endif
+
+ pthread_rwlock_destroy(&(mutex->mutex));
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_read(Eina_RWLock *mutex)
+{
+#ifdef EINA_HAVE_ON_OFF_THREADS
+ if (!_eina_threads_activated)
+ {
+#ifdef EINA_HAVE_DEBUG_THREADS
+ assert(pthread_equal(_eina_main_loop, pthread_self()));
+#endif
+ return EINA_LOCK_SUCCEED;
+ }
+#endif
+
+ if (pthread_rwlock_rdlock(&(mutex->mutex)) != 0)
+ return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_write(Eina_RWLock *mutex)
+{
+#ifdef EINA_HAVE_ON_OFF_THREADS
+ if (!_eina_threads_activated)
+ {
+#ifdef EINA_HAVE_DEBUG_THREADS
+ assert(pthread_equal(_eina_main_loop, pthread_self()));
+#endif
+ return EINA_LOCK_SUCCEED;
+ }
+#endif
+
+ if (pthread_rwlock_wrlock(&(mutex->mutex)) != 0)
+ return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_release(Eina_RWLock *mutex)
+{
+#ifdef EINA_HAVE_ON_OFF_THREADS
+ if (!_eina_threads_activated)
+ {
+#ifdef EINA_HAVE_DEBUG_THREADS
+ assert(pthread_equal(_eina_main_loop, pthread_self()));
+#endif
+ return EINA_LOCK_SUCCEED;
+ }
+#endif
+
+ if (pthread_rwlock_unlock(&(mutex->mutex)) != 0)
+ return EINA_LOCK_FAIL;
+ return EINA_LOCK_SUCCEED;
+}
#endif
* Abtract type for a mutual exclusive object.
*/
typedef void *Eina_Lock;
+typedef void *Eina_RWLock;
typedef void *Eina_Condition;
/**
return EINA_FALSE;
}
+static inline Eina_Bool
+eina_rwlock_new(Eina_RWLock *mutex EINA_UNUSED)
+{
+ return EINA_FALSE;
+}
+
+static inline void
+ eina_rwlock_free(Eina_RWLock *mutex EINA_UNUSED)
+{
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_read_take(Eina_RWLock *mutex EINA_UNUSED)
+{
+ return EINA_LOCK_FAIL;
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_write_take(Eina_RWLock *mutex EINA_UNUSED)
+{
+ return EINA_LOCK_FAIL;
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_release(Eina_RWLock *mutex)
+{
+ return EINA_LOCK_FAIL;
+}
+
/**
* @}
*/
};
#endif
+typedef struct _Eina_Win32_RWLock Eina_RWLock;
+
+struct _Eina_Win32_RWLock
+{
+ LONG readers_count;
+ LONG writers_count;
+ int readers;
+ int writers;
+
+ Eina_Lock mutex;
+ Eina_Condition cond_read;
+ Eina_Condition cond_write;
+};
EAPI extern Eina_Bool _eina_threads_activated;
#endif
}
+static inline Eina_Bool
+eina_rwlock_new(Eina_RWLock *mutex)
+{
+ if (!eina_lock_new(&(mutex->mutex))) return EINA_FALSE;
+ if (!eina_condition_new(&(mutex->cond_read), &(mutex->mutex)))
+ goto on_error1;
+ if (!eina_condition_new(&(mutex->cond_write), &(mutex->mutex)))
+ goto on_error2;
+
+ return EINA_TRUE;
+
+ on_error2:
+ eina_condition_free(&(mutex->cond_read));
+ on_error1:
+ eina_lock_free(&(mutex->mutex));
+ return EINA_FALSE;
+}
+
+static inline void
+eina_rwlock_free(Eina_RWLock *mutex)
+{
+ eina_condition_free(&(mutex->cond_read));
+ eina_condition_free(&(mutex->cond_write));
+ eina_lock_free(&(mutex->mutex));
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_read(Eina_RWLock *mutex)
+{
+ DWORD res;
+
+ eina_lock_take(&(x->mutex));
+ if (mutex->writers)
+ {
+ mutex->readers_count++;
+ while (mutex->writers)
+ {
+ EnterCriticalSection(&mutex->cond_write->waiters_count_lock);
+ mutex->cond_read->waiters_count++;
+ LeaveCriticalSection(&mutex->cond_write->waiters_count_lock);
+ res = WaitForSingleObject(mutex->cond_write->semaphore, INFINITE);
+ if (res != WAIT_OBJECT_0) break;
+ }
+ mutex->readers_count--;
+ }
+ if (res == 0)
+ mutex->readers++;
+ eina_lock_release(&(mutex->mutex));
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_write(Eina_RWLock *mutex)
+{
+ DWORD res;
+
+ eina_lock_take(&(mutex->mutex));
+ if (mutex->writers || mutex->readers > 0)
+ {
+ mutex->writers_count++;
+ while (mutex->writers || mutex->readers > 0)
+ {
+ EnterCriticalSection(&mutex->cond_write->waiters_count_lock);
+ mutex->cond_read->waiters_count++;
+ LeaveCriticalSection(&mutex->cond_write->waiters_count_lock);
+ res = WaitForSingleObject(mutex->cond_write->semaphore, INFINITE);
+ if (res != WAIT_OBJECT_0) break;
+ }
+ mutex->writers_count--;
+ }
+ if (res == 0) x->writers_count = 1;
+ eina_lock_release(&(mutex->mutex));
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_release(Eina_RWLock *mutex)
+{
+ eina_lock_take(&(mutex->mutex));
+
+ if (mutex->writers)
+ {
+ mutex->writers = 0;
+ if (mutex->readers_count == 1)
+ {
+ EnterCriticalSection(&mutex->cond_read->waiters_count_lock);
+ if (mutex->cond_read->waiters_count > 0)
+ ReleaseSemaphore(x->cond_read->semaphore, 1, 0);
+ LeaveCriticalSection(&mutex->cond_read->threads_count_lock);
+ }
+ else if (mutex->readers_count > 0)
+ eina_condition_broadast(&(mutex->cond_read));
+ else if (mutex->writers_count > 0)
+ {
+ EnterCriticalSection (&mutex->cond_write->waiters_count_lock);
+ if (mutex->cond_write->waiters_count > 0)
+ ReleaseSemaphore(mutex->cond_write->semaphore, 1, 0);
+ LeaveCriticalSection (&mutex->cond_write->waiters_count_lock);
+ }
+ }
+ else if (mutex->readers > 0)
+ {
+ mutex->readers--;
+ if (mutex->readers == 0 && mutex->writers_count > 0)
+ {
+ EnterCriticalSection (&mutex->cond_write->waiters_count_lock);
+ if (mutex->cond_write->waiters_count > 0)
+ ReleaseSemaphore(mutex->cond_write->semaphore, 1, 0);
+ LeaveCriticalSection (&mutex->cond_write->waiters_count_lock);
+ }
+ }
+ eina_lock_release(&(mutex->mutex));
+}
+
#endif
EAPI extern Eina_Bool _threads_activated;
typedef HANDLE Eina_Lock;
+typedef Eina_Lock Eina_RWLock;
static inline Eina_Bool
eina_lock_new(Eina_Lock *mutex)
return EINA_FALSE;
}
+static inline Eina_Bool
+eina_rwlock_new(Eina_RWLock *mutex)
+{
+ return eina_lock_new(mutex);
+}
+
+static inline void
+eina_rwlock_free(Eina_RWLock *mutex)
+{
+ return eina_lock_free(mutex);
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_read(Eina_RWLock *mutex)
+{
+ return eina_lock_take(mutex);
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_take_write(Eina_RWLock *mutex)
+{
+ return eina_lock_take(mutex);
+}
+
+static inline Eina_Lock_Result
+eina_rwlock_release(Eina_RWLock *mutex)
+{
+ return eina_lock_release(mutex);
+}
#endif
static inline Eina_Bool eina_condition_broadcast(Eina_Condition *cond);
static inline Eina_Bool eina_condition_signal(Eina_Condition *cond);
+static inline Eina_Bool eina_rwlock_new(Eina_RWLock *mutex);
+static inline void eina_rwlock_free(Eina_RWLock *mutex);
+static inline Eina_Lock_Result eina_rwlock_take_read(Eina_RWLock *mutex);
+static inline Eina_Lock_Result eina_rwlock_take_write(Eina_RWLock *mutex);
+static inline Eina_Lock_Result eina_rwlock_release(Eina_RWLock *mutex);
+
/**
* @}
*/