eina: add Eina_LockRW. more refactoring code comming.

SVN revision: 60628
This commit is contained in:
Cedric BAIL 2011-06-23 09:58:54 +00:00
parent c83256416a
commit a5fe2772c7
6 changed files with 279 additions and 0 deletions

View File

@ -110,3 +110,7 @@
* 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.

View File

@ -40,6 +40,7 @@ typedef void (*Eina_Lock_Bt_Func) ();
#endif
typedef struct _Eina_Lock Eina_Lock;
typedef struct _Eina_RWLock Eina_RWLock;
typedef struct _Eina_Condition Eina_Condition;
struct _Eina_Lock
@ -62,6 +63,14 @@ struct _Eina_Condition
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
@ -353,5 +362,80 @@ eina_condition_signal(Eina_Condition *cond)
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

View File

@ -44,6 +44,7 @@
* Abtract type for a mutual exclusive object.
*/
typedef void *Eina_Lock;
typedef void *Eina_RWLock;
typedef void *Eina_Condition;
/**
@ -173,6 +174,35 @@ eina_condition_signal(Eina_Condition *cond EINA_UNUSED)
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;
}
/**
* @}
*/

View File

@ -42,6 +42,19 @@ struct _Eina_Condition
};
#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;
@ -297,4 +310,116 @@ eina_condition_signal(Eina_Condition *cond)
#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

View File

@ -24,6 +24,7 @@
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)
@ -113,5 +114,34 @@ eina_condition_signal(Eina_Condition *cond)
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

View File

@ -67,6 +67,12 @@ static inline Eina_Bool eina_condition_timedwait(Eina_Condition *cond, double t)
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);
/**
* @}
*/