]> git.sesse.net Git - vlc/blobdiff - src/misc/w32thread.c
vlc_clone(): abide by --rt-priority and --rt-offset
[vlc] / src / misc / w32thread.c
index a62e530b458d18ecb28c1a4cc869d225b44c9acb..a2ef9eca272ee5e561154152fa1983a733891c94 100644 (file)
@@ -34,6 +34,7 @@
 #include "libvlc.h"
 #include <stdarg.h>
 #include <assert.h>
+#include <limits.h>
 
 static vlc_threadvar_t cancel_key;
 
@@ -53,7 +54,7 @@ typedef struct vlc_cancel_t
 #ifndef UNDER_CE
 # define VLC_CANCEL_INIT { NULL, true, false }
 #else
-# define VLC_CANCEL_INIT { NULL, NULL; true, false }
+# define VLC_CANCEL_INIT { NULL, NULL, true, false }
 #endif
 
 #ifdef UNDER_CE
@@ -158,20 +159,18 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
 }
 
 /*** Mutexes ***/
-int vlc_mutex_init( vlc_mutex_t *p_mutex )
+void vlc_mutex_init( vlc_mutex_t *p_mutex )
 {
     /* This creates a recursive mutex. This is OK as fast mutexes have
      * no defined behavior in case of recursive locking. */
     InitializeCriticalSection (&p_mutex->mutex);
     p_mutex->initialized = 1;
-    return 0;
 }
 
-int vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
+void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
 {
     InitializeCriticalSection( &p_mutex->mutex );
     p_mutex->initialized = 1;
-    return 0;
 }
 
 
@@ -220,11 +219,12 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
 }
 
 /*** Condition variables ***/
-int vlc_cond_init( vlc_cond_t *p_condvar )
+void vlc_cond_init( vlc_cond_t *p_condvar )
 {
     /* Create a manual-reset event (manual reset is needed for broadcast). */
     *p_condvar = CreateEvent (NULL, TRUE, FALSE, NULL);
-    return *p_condvar ? 0 : ENOMEM;
+    if (!*p_condvar)
+        abort();
 }
 
 void vlc_cond_destroy (vlc_cond_t *p_condvar)
@@ -292,6 +292,79 @@ int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
     return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
 }
 
+/*** Read/write locks */
+/* SRW (Slim Read Write) locks are available in Vista+ only */
+void vlc_rwlock_init (vlc_rwlock_t *lock)
+{
+    vlc_mutex_init (&lock->mutex);
+    vlc_cond_init (&lock->read_wait);
+    vlc_cond_init (&lock->write_wait);
+    lock->readers = 0; /* active readers */
+    lock->writers = 0; /* waiting or active writers */
+    lock->writer = 0; /* ID of active writer */
+}
+
+/**
+ * Destroys an initialized unused read/write lock.
+ */
+void vlc_rwlock_destroy (vlc_rwlock_t *lock)
+{
+    vlc_cond_destroy (&lock->read_wait);
+    vlc_cond_destroy (&lock->write_wait);
+    vlc_mutex_destroy (&lock->mutex);
+}
+
+/**
+ * Acquires a read/write lock for reading. Recursion is allowed.
+ */
+void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    while (lock->writer != 0)
+        vlc_cond_wait (&lock->read_wait, &lock->mutex);
+    if (lock->readers == ULONG_MAX)
+        abort ();
+    lock->readers++;
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+/**
+ * Acquires a read/write lock for writing. Recursion is not allowed.
+ */
+void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    if (lock->writers == ULONG_MAX)
+        abort ();
+    lock->writers++;
+    while ((lock->readers > 0) || (lock->writer != 0))
+        vlc_cond_wait (&lock->write_wait, &lock->mutex);
+    lock->writers--;
+    lock->writer = GetCurrentThreadId ();
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+/**
+ * Releases a read/write lock.
+ */
+void vlc_rwlock_unlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    if (lock->readers > 0)
+        lock->readers--; /* Read unlock */
+    else
+        lock->writer = 0; /* Write unlock */
+
+    if (lock->writers > 0)
+    {
+        if (lock->readers == 0)
+            vlc_cond_signal (&lock->write_wait);
+    }
+    else
+        vlc_cond_broadcast (&lock->read_wait);
+    vlc_mutex_unlock (&lock->mutex);
+}
+
 /*** Thread-specific variables (TLS) ***/
 int vlc_threadvar_create (vlc_threadvar_t *p_tls, void (*destr) (void *))
 {
@@ -329,6 +402,11 @@ void *vlc_threadvar_get (vlc_threadvar_t key)
 
 
 /*** Threads ***/
+void vlc_threads_setup (libvlc_int_t *p_libvlc)
+{
+    (void) p_libvlc;
+}
+
 static unsigned __stdcall vlc_entry (void *data)
 {
     vlc_cancel_t cancel_data = VLC_CANCEL_INIT;
@@ -511,3 +589,53 @@ void vlc_control_cancel (int cmd, ...)
     }
     va_end (ap);
 }
+
+
+/*** Timers ***/
+static void CALLBACK vlc_timer_do (void *val, BOOLEAN timeout)
+{
+    vlc_timer_t *id = val;
+
+    assert (timeout);
+    id->func (id->data);
+}
+
+int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
+{
+    id->func = func;
+    id->data = data;
+    id->handle = INVALID_HANDLE_VALUE;
+    return 0;
+}
+
+void vlc_timer_destroy (vlc_timer_t *id)
+{
+    if (id->handle != INVALID_HANDLE_VALUE)
+        DeleteTimerQueueTimer (NULL, id->handle, NULL);
+}
+
+void vlc_timer_schedule (vlc_timer_t *id, bool absolute,
+                         mtime_t value, mtime_t interval)
+{
+    if (id->handle != INVALID_HANDLE_VALUE)
+    {
+        DeleteTimerQueueTimer (NULL, id->handle, NULL);
+        id->handle = INVALID_HANDLE_VALUE;
+    }
+    if (value == 0)
+        return; /* Disarm */
+
+    if (absolute)
+        value -= mdate ();
+    value = (value + 999) / 1000;
+    interval = (interval + 999) / 1000;
+    if (!CreateTimerQueueTimer (&id->handle, NULL, vlc_timer_do, id, value,
+                                interval, WT_EXECUTEDEFAULT))
+        abort ();
+}
+
+unsigned vlc_timer_getoverrun (const vlc_timer_t *id)
+{
+    (void)id;
+    return 0;
+}