Implement thread semaphores
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 12 Sep 2009 11:26:33 +0000 (14:26 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Sat, 12 Sep 2009 11:26:33 +0000 (14:26 +0300)
include/vlc_threads.h
src/libvlccore.sym
src/misc/pthread.c
src/misc/w32thread.c

index 7d65e4f..1f69541 100644 (file)
@@ -48,8 +48,7 @@
 #   include <stdlib.h> /* lldiv_t definition (only in C99) */
 #   include <unistd.h> /* _POSIX_SPIN_LOCKS */
 #   include <pthread.h>
-    /* Needed for pthread_cond_timedwait */
-#   include <errno.h>
+#   include <semaphore.h>
 #   include <time.h>
 
 #endif
@@ -107,6 +106,7 @@ typedef pthread_t       vlc_thread_t;
 typedef pthread_mutex_t vlc_mutex_t;
 #define VLC_STATIC_MUTEX PTHREAD_MUTEX_INITIALIZER
 typedef pthread_cond_t  vlc_cond_t;
+typedef sem_t           vlc_sem_t;
 typedef pthread_rwlock_t vlc_rwlock_t;
 typedef pthread_key_t   vlc_threadvar_t;
 typedef struct vlc_timer *vlc_timer_t;
@@ -130,6 +130,7 @@ typedef struct
 #define VLC_STATIC_MUTEX { 0, }
 
 typedef HANDLE  vlc_cond_t;
+typedef HANDLE  vlc_sem_t;
 
 typedef struct
 {
@@ -163,7 +164,12 @@ VLC_EXPORT( void, vlc_cond_destroy,  ( vlc_cond_t * ) );
 VLC_EXPORT( void, vlc_cond_signal, (vlc_cond_t *) );
 VLC_EXPORT( void, vlc_cond_broadcast, (vlc_cond_t *) );
 VLC_EXPORT( void, vlc_cond_wait, (vlc_cond_t *, vlc_mutex_t *) );
-VLC_EXPORT( int, vlc_cond_timedwait, (vlc_cond_t *, vlc_mutex_t *, mtime_t) );
+VLC_EXPORT( int,  vlc_cond_timedwait, (vlc_cond_t *, vlc_mutex_t *, mtime_t) );
+VLC_EXPORT( void, vlc_sem_init, (vlc_sem_t *, unsigned) );
+VLC_EXPORT( void, vlc_sem_destroy, (vlc_sem_t *) );
+VLC_EXPORT( int,  vlc_sem_post, (vlc_sem_t *) );
+VLC_EXPORT( void, vlc_sem_wait, (vlc_sem_t *) );
+
 VLC_EXPORT( void, vlc_rwlock_init, (vlc_rwlock_t *) );
 VLC_EXPORT( void, vlc_rwlock_destroy, (vlc_rwlock_t *) );
 VLC_EXPORT( void, vlc_rwlock_rdlock, (vlc_rwlock_t *) );
index 2eeb208..da2f4b6 100644 (file)
@@ -463,6 +463,10 @@ vlc_cond_init
 vlc_cond_signal
 vlc_cond_timedwait
 vlc_cond_wait
+vlc_sem_init
+vlc_sem_destroy
+vlc_sem_post
+vlc_sem_wait
 vlc_control_cancel
 vlc_CPU
 vlc_error
index 41c09d8..ce604f4 100644 (file)
@@ -378,6 +378,48 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
     return val;
 }
 
+/**
+ * Initializes a semaphore.
+ */
+void vlc_sem_init (vlc_sem_t *sem, unsigned value)
+{
+    if (sem_init (sem, 0, value))
+        abort ();
+}
+
+/**
+ * Destroys a semaphore.
+ */
+void vlc_sem_destroy (vlc_sem_t *sem)
+{
+    int val = sem_destroy (sem);
+    VLC_THREAD_ASSERT ("destroying semaphore");
+}
+
+/**
+ * Increments the value of a semaphore.
+ */
+int vlc_sem_post (vlc_sem_t *sem)
+{
+    int val = sem_post (sem);
+    if (val != EOVERFLOW)
+        VLC_THREAD_ASSERT ("unlocking semaphore");
+    return val;
+}
+
+/**
+ * Atomically wait for the semaphore to become non-zero (if needed),
+ * then decrements it.
+ */
+void vlc_sem_wait (vlc_sem_t *sem)
+{
+    int val;
+    do
+        val = sem_wait (sem);
+    while (val == EINTR);
+    VLC_THREAD_ASSERT ("locking semaphore");
+}
+
 /**
  * Initializes a read/write lock.
  */
index 3669a94..ee83a9f 100644 (file)
@@ -296,6 +296,37 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
     return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
 }
 
+/*** Semaphore ***/
+void vlc_sem_init (vlc_sem_t *sem, unsigned value)
+{
+    *sem = CreateSemaphore (NULL, value, 0x7fffffff, NULL);
+    if (*sem == NULL)
+        abort ();
+}
+
+void vlc_sem_destroy (vlc_sem_t *sem)
+{
+    CloseHandle (*sem);
+}
+
+int vlc_sem_post (vlc_sem_t *sem)
+{
+    ReleaseSemaphore (*sem, 1, NULL);
+    return 0; /* FIXME */
+}
+
+void vlc_sem_wait (vlc_sem_t *sem)
+{
+    DWORD result;
+
+    do
+    {
+        vlc_testcancel ();
+        result = WaitForSingleObjectEx (*sem, INFINITE, TRUE);
+    }
+    while (result == WAIT_IO_COMPLETION);
+}
+
 /*** Read/write locks */
 /* SRW (Slim Read Write) locks are available in Vista+ only */
 void vlc_rwlock_init (vlc_rwlock_t *lock)