eina: add Eina_LockRW. more refactoring code comming.
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Jun 2011 09:58:54 +0000 (09:58 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Jun 2011 09:58:54 +0000 (09:58 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@60628 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/include/eina_inline_lock_posix.x
src/include/eina_inline_lock_void.x
src/include/eina_inline_lock_win32.x
src/include/eina_inline_lock_wince.x
src/include/eina_lock.h

index a1a8e21..d36ad6e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
        * 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.
index c1026d4..1c54fca 100644 (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
index 6bcf151..2c849ac 100644 (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;
+}
+
 /**
  * @}
  */
index d495b6f..07dfbd4 100644 (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
index 65145be..1be0890 100644 (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
index 2dbeaba..21aa431 100644 (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);
+
 /**
  * @}
  */