Write generic semaphore back-end and merge generic thread code
authorRémi Denis-Courmont <remi@remlab.net>
Tue, 11 Sep 2012 09:31:14 +0000 (12:31 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 11 Sep 2012 09:31:14 +0000 (12:31 +0300)
include/vlc_threads.h
src/Makefile.am
src/misc/rwlock.c [deleted file]
src/misc/threads.c
src/os2/thread.c

index 4dd6335..cc0e8b1 100644 (file)
@@ -158,8 +158,8 @@ typedef struct
 } vlc_cond_t;
 #define VLC_STATIC_COND { 0, 0 }
 
-typedef HANDLE  vlc_sem_t;
-typedef struct vlc_rwlock vlc_rwlock_t;
+typedef HANDLE vlc_sem_t;
+#define LIBVLC_NEED_RWLOCK
 typedef struct vlc_threadvar *vlc_threadvar_t;
 typedef struct vlc_timer *vlc_timer_t;
 
@@ -188,27 +188,29 @@ typedef struct
 } vlc_cond_t;
 #define VLC_STATIC_COND { 0, 0 }
 
-typedef struct
-{
-    HEV  hev;
-    HMTX wait_mutex;
-    HMTX count_mutex;
-    int  count;
-} vlc_sem_t;
-
-typedef struct vlc_rwlock vlc_rwlock_t;
+#define LIBVLC_NEED_SEMAPHORE
+#define LIBVLC_NEED_RWLOCK
 typedef struct vlc_threadvar *vlc_threadvar_t;
 typedef struct vlc_timer *vlc_timer_t;
 
 #endif
 
-#ifndef VLC_STATIC_RWLOCK
-struct vlc_rwlock
+#ifdef LIBVLC_NEED_SEMAPHORE
+typedef struct vlc_sem
+{
+    vlc_mutex_t lock;
+    vlc_cond_t  wait;
+    unsigned    value;
+} vlc_sem_t;
+#endif
+
+#ifdef LIBVLC_NEED_RWLOCK
+typedef struct vlc_rwlock
 {
     vlc_mutex_t   mutex;
     vlc_cond_t    wait;
     long          state;
-};
+} vlc_rwlock_t;
 # define VLC_STATIC_RWLOCK { VLC_STATIC_MUTEX, VLC_STATIC_COND, 0 }
 #endif
 
index 8f9a237..9ac25d3 100644 (file)
@@ -269,7 +269,6 @@ SOURCES_libvlc_win32 = \
        win32/dirs.c \
        win32/filesystem.c \
        win32/plugin.c \
-       misc/rwlock.c \
        win32/thread.c \
        win32/specific.c \
        win32/winsock.c \
@@ -288,7 +287,6 @@ SOURCES_libvlc_os2 = \
        os2/dirs.c \
        os2/filesystem.c \
        os2/plugin.c \
-       misc/rwlock.c \
        os2/thread.c \
        os2/specific.c \
        os2/rand.c \
diff --git a/src/misc/rwlock.c b/src/misc/rwlock.c
deleted file mode 100644 (file)
index bb1c27b..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*****************************************************************************
- * rwlock.h : generic back-end for LibVLC read/write locks
- *****************************************************************************
- * Copyright (C) 2009-2012 Rémi Denis-Courmont
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
- *****************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <limits.h>
-#include <assert.h>
-
-#include <vlc_common.h>
-
-/* NOTE:
- * lock->state is a signed long integer:
- *  - The sign bit is set when the lock is held for writing.
- *  - The other bits code the number of times the lock is held for reading.
- * Consequently:
- *  - The value is negative if and only if the lock is held for writing.
- *  - The value is zero if and only if the lock is not held at all.
- */
-#define READER_MASK LONG_MAX
-#define WRITER_BIT  LONG_MIN
-
-void vlc_rwlock_init (vlc_rwlock_t *lock)
-{
-    vlc_mutex_init (&lock->mutex);
-    vlc_cond_init (&lock->wait);
-    lock->state = 0;
-}
-
-void vlc_rwlock_destroy (vlc_rwlock_t *lock)
-{
-    vlc_cond_destroy (&lock->wait);
-    vlc_mutex_destroy (&lock->mutex);
-}
-
-void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    /* Recursive read-locking is allowed.
-     * Ensure that there is no active writer. */
-    while (lock->state < 0)
-    {
-        assert (lock->state == WRITER_BIT);
-        mutex_cleanup_push (&lock->mutex);
-        vlc_cond_wait (&lock->wait, &lock->mutex);
-        vlc_cleanup_pop ();
-    }
-    if (unlikely(lock->state >= READER_MASK))
-        abort (); /* An overflow is certainly a recursion bug. */
-    lock->state++;
-    vlc_mutex_unlock (&lock->mutex);
-}
-
-void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    /* Wait until nobody owns the lock in any way. */
-    while (lock->state != 0)
-    {
-        mutex_cleanup_push (&lock->mutex);
-        vlc_cond_wait (&lock->wait, &lock->mutex);
-        vlc_cleanup_pop ();
-    }
-    lock->state = WRITER_BIT;
-    vlc_mutex_unlock (&lock->mutex);
-}
-
-void vlc_rwlock_unlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    if (lock->state < 0)
-    {   /* Write unlock */
-        assert (lock->state == WRITER_BIT);
-        /* Let reader and writer compete. OS scheduler decides who wins. */
-        lock->state = 0;
-        vlc_cond_broadcast (&lock->wait);
-    }
-    else
-    {   /* Read unlock */
-        assert (lock->state > 0);
-        /* If there are no readers left, wake up one pending writer. */
-        if (--lock->state == 0)
-            vlc_cond_signal (&lock->wait);
-    }
-    vlc_mutex_unlock (&lock->mutex);
-}
index 2e7dc35..13e0437 100644 (file)
@@ -1,14 +1,7 @@
 /*****************************************************************************
- * threads.c : threads implementation for the VideoLAN client
+ * threads.c: LibVLC generic thread support
  *****************************************************************************
- * Copyright (C) 1999-2008 VLC authors and VideoLAN
- * $Id$
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *          Samuel Hocevar <sam@zoy.org>
- *          Gildas Bazin <gbazin@netcourrier.com>
- *          Clément Sténac
- *          Rémi Denis-Courmont
+ * Copyright (C) 2009-2012 Rémi Denis-Courmont
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
 # include "config.h"
 #endif
 
-#include <vlc_common.h>
 #include <assert.h>
 
+#include <vlc_common.h>
+
 /*** Global locks ***/
 
 void vlc_global_mutex (unsigned n, bool acquire)
@@ -54,3 +48,127 @@ void vlc_global_mutex (unsigned n, bool acquire)
     else
         vlc_mutex_unlock (lock);
 }
+
+#ifdef LIBVLC_NEED_RWLOCK
+/*** Generic read/write locks ***/
+#include <stdlib.h>
+#include <limits.h>
+/* NOTE:
+ * lock->state is a signed long integer:
+ *  - The sign bit is set when the lock is held for writing.
+ *  - The other bits code the number of times the lock is held for reading.
+ * Consequently:
+ *  - The value is negative if and only if the lock is held for writing.
+ *  - The value is zero if and only if the lock is not held at all.
+ */
+#define READER_MASK LONG_MAX
+#define WRITER_BIT  LONG_MIN
+
+void vlc_rwlock_init (vlc_rwlock_t *lock)
+{
+    vlc_mutex_init (&lock->mutex);
+    vlc_cond_init (&lock->wait);
+    lock->state = 0;
+}
+
+void vlc_rwlock_destroy (vlc_rwlock_t *lock)
+{
+    vlc_cond_destroy (&lock->wait);
+    vlc_mutex_destroy (&lock->mutex);
+}
+
+void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    /* Recursive read-locking is allowed.
+     * Ensure that there is no active writer. */
+    while (lock->state < 0)
+    {
+        assert (lock->state == WRITER_BIT);
+        mutex_cleanup_push (&lock->mutex);
+        vlc_cond_wait (&lock->wait, &lock->mutex);
+        vlc_cleanup_pop ();
+    }
+    if (unlikely(lock->state >= READER_MASK))
+        abort (); /* An overflow is certainly a recursion bug. */
+    lock->state++;
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    /* Wait until nobody owns the lock in any way. */
+    while (lock->state != 0)
+    {
+        mutex_cleanup_push (&lock->mutex);
+        vlc_cond_wait (&lock->wait, &lock->mutex);
+        vlc_cleanup_pop ();
+    }
+    lock->state = WRITER_BIT;
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+void vlc_rwlock_unlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    if (lock->state < 0)
+    {   /* Write unlock */
+        assert (lock->state == WRITER_BIT);
+        /* Let reader and writer compete. OS scheduler decides who wins. */
+        lock->state = 0;
+        vlc_cond_broadcast (&lock->wait);
+    }
+    else
+    {   /* Read unlock */
+        assert (lock->state > 0);
+        /* If there are no readers left, wake up one pending writer. */
+        if (--lock->state == 0)
+            vlc_cond_signal (&lock->wait);
+    }
+    vlc_mutex_unlock (&lock->mutex);
+}
+#endif /* LIBVLC_NEED_RWLOCK */
+
+#ifdef LIBVLC_NEED_SEMAPHORE
+/*** Generic semaphores ***/
+#include <limits.h>
+#include <errno.h>
+
+void vlc_sem_init (vlc_sem_t *sem, unsigned value)
+{
+    vlc_mutex_init (&sem->lock);
+    vlc_cond_init (&sem->wait);
+    sem->value = value;
+}
+
+void vlc_sem_destroy (vlc_sem_t *sem)
+{
+    vlc_cond_destroy (&sem->wait);
+    vlc_mutex_destroy (&sem->lock);
+}
+
+int vlc_sem_post (vlc_sem_t *sem)
+{
+    int ret = 0;
+
+    vlc_mutex_lock (&sem->lock);
+    if (likely(sem->value != UINT_MAX))
+        sem->value++;
+    else
+        ret = EOVERFLOW;
+    vlc_mutex_unlock (&sem->lock);
+    vlc_cond_signal (&sem->wait);
+
+    return ret;
+}
+
+void vlc_sem_wait (vlc_sem_t *sem)
+{
+    vlc_mutex_lock (&sem->lock);
+    while (!sem->value)
+        vlc_cond_wait (&sem->wait, &sem->lock);
+    sem->value--;
+    vlc_mutex_unlock (&sem->lock);
+}
+#endif /* LIBVLC_NEED_SEMAPHORE */
index a1cdd62..7e1f763 100644 (file)
@@ -360,74 +360,6 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
     return rc ? ETIMEDOUT : 0;
 }
 
-/*** Semaphore ***/
-void vlc_sem_init (vlc_sem_t *sem, unsigned value)
-{
-    if (DosCreateEventSem(NULL, &sem->hev, 0, value > 0 ? TRUE : FALSE))
-        abort ();
-
-    if (DosCreateMutexSem(NULL, &sem->wait_mutex, 0, FALSE))
-        abort ();
-
-    if (DosCreateMutexSem(NULL, &sem->count_mutex, 0, FALSE))
-        abort ();
-
-    sem->count = value;
-}
-
-void vlc_sem_destroy (vlc_sem_t *sem)
-{
-    DosCloseEventSem (sem->hev);
-    DosCloseMutexSem (sem->wait_mutex);
-    DosCloseMutexSem (sem->count_mutex);
-}
-
-int vlc_sem_post (vlc_sem_t *sem)
-{
-    DosRequestMutexSem(sem->count_mutex, SEM_INDEFINITE_WAIT);
-
-    if (sem->count < 0x7FFFFFFF)
-    {
-        sem->count++;
-        DosPostEventSem(sem->hev);
-    }
-
-    DosReleaseMutexSem(sem->count_mutex);
-
-    return 0; /* FIXME */
-}
-
-void vlc_sem_wait (vlc_sem_t *sem)
-{
-    ULONG rc;
-
-    do
-    {
-        vlc_testcancel ();
-
-        DosRequestMutexSem(sem->wait_mutex, SEM_INDEFINITE_WAIT);
-
-        rc = vlc_WaitForSingleObject (sem->hev, SEM_INDEFINITE_WAIT );
-
-        if (!rc)
-        {
-            DosRequestMutexSem(sem->count_mutex, SEM_INDEFINITE_WAIT);
-
-            sem->count--;
-            if (sem->count == 0)
-            {
-                ULONG ulPost;
-
-                DosResetEventSem(sem->hev, &ulPost);
-            }
-
-            DosReleaseMutexSem(sem->count_mutex);
-        }
-
-        DosReleaseMutexSem(sem->wait_mutex);
-    } while (rc == ERROR_INTERRUPT);
-}
-
 /*** Thread-specific variables (TLS) ***/
 struct vlc_threadvar
 {