]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/w32pthreads.h
cabac: split cabac.h into declarations and function definitions
[ffmpeg] / libavcodec / w32pthreads.h
index 77748175185a69902fad1d04676b54f87a82af5c..70b84cf2e17e6482a000ce24a586a5aa028b93d8 100644 (file)
@@ -91,17 +91,36 @@ static void pthread_join(pthread_t thread, void **value_ptr)
     CloseHandle(thread.handle);
 }
 
-#define pthread_mutex_init(m, a) InitializeCriticalSection(m)
-#define pthread_mutex_destroy(m) DeleteCriticalSection(m)
-#define pthread_mutex_lock(m)    EnterCriticalSection(m)
-#define pthread_mutex_unlock(m)  LeaveCriticalSection(m)
+static inline int pthread_mutex_init(pthread_mutex_t *m, void* attr)
+{
+    InitializeCriticalSection(m);
+    return 0;
+}
+static inline int pthread_mutex_destroy(pthread_mutex_t *m)
+{
+    DeleteCriticalSection(m);
+    return 0;
+}
+static inline int pthread_mutex_lock(pthread_mutex_t *m)
+{
+    EnterCriticalSection(m);
+    return 0;
+}
+static inline int pthread_mutex_unlock(pthread_mutex_t *m)
+{
+    LeaveCriticalSection(m);
+    return 0;
+}
 
 /* for pre-Windows 6.0 platforms we need to define and use our own condition
  * variable and api */
 typedef struct {
+    pthread_mutex_t mtx_broadcast;
     pthread_mutex_t mtx_waiter_count;
     volatile int waiter_count;
     HANDLE semaphore;
+    HANDLE waiters_done;
+    volatile int is_broadcast;
 } win32_cond_t;
 
 static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
@@ -120,8 +139,12 @@ static void pthread_cond_init(pthread_cond_t *cond, const void *unused_attr)
     win32_cond->semaphore = CreateSemaphore(NULL, 0, 0x7fffffff, NULL);
     if (!win32_cond->semaphore)
         return;
+    win32_cond->waiters_done = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (!win32_cond->waiters_done)
+        return;
 
     pthread_mutex_init(&win32_cond->mtx_waiter_count, NULL);
+    pthread_mutex_init(&win32_cond->mtx_broadcast, NULL);
 }
 
 static void pthread_cond_destroy(pthread_cond_t *cond)
@@ -133,7 +156,9 @@ static void pthread_cond_destroy(pthread_cond_t *cond)
 
     /* non native condition variables */
     CloseHandle(win32_cond->semaphore);
+    CloseHandle(win32_cond->waiters_done);
     pthread_mutex_destroy(&win32_cond->mtx_waiter_count);
+    pthread_mutex_destroy(&win32_cond->mtx_broadcast);
     av_freep(&win32_cond);
     cond->ptr = NULL;
 }
@@ -141,53 +166,89 @@ static void pthread_cond_destroy(pthread_cond_t *cond)
 static void pthread_cond_broadcast(pthread_cond_t *cond)
 {
     win32_cond_t *win32_cond = cond->ptr;
+    int have_waiter;
+
     if (cond_broadcast) {
         cond_broadcast(cond);
         return;
     }
 
     /* non native condition variables */
+    pthread_mutex_lock(&win32_cond->mtx_broadcast);
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+    have_waiter = 0;
+
     if (win32_cond->waiter_count) {
-        ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
-        win32_cond->waiter_count = 0;
+        win32_cond->is_broadcast = 1;
+        have_waiter = 1;
     }
-    pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+
+    if (have_waiter) {
+        ReleaseSemaphore(win32_cond->semaphore, win32_cond->waiter_count, NULL);
+        pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+        WaitForSingleObject(win32_cond->waiters_done, INFINITE);
+        ResetEvent(win32_cond->waiters_done);
+        win32_cond->is_broadcast = 0;
+    } else
+        pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
 }
 
 static void pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
     win32_cond_t *win32_cond = cond->ptr;
+    int last_waiter;
     if (cond_wait) {
         cond_wait(cond, mutex, INFINITE);
         return;
     }
 
     /* non native condition variables */
+    pthread_mutex_lock(&win32_cond->mtx_broadcast);
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
     win32_cond->waiter_count++;
     pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
 
+    // unlock the external mutex
     pthread_mutex_unlock(mutex);
     WaitForSingleObject(win32_cond->semaphore, INFINITE);
-    pthread_mutex_lock(mutex);
+
+    pthread_mutex_lock(&win32_cond->mtx_waiter_count);
+    win32_cond->waiter_count--;
+    last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
+    pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+
+    if (last_waiter)
+        SetEvent(win32_cond->waiters_done);
+
+    // lock the external mutex
+    return pthread_mutex_lock(mutex);
 }
 
 static void pthread_cond_signal(pthread_cond_t *cond)
 {
     win32_cond_t *win32_cond = cond->ptr;
+    int have_waiter;
     if (cond_signal) {
         cond_signal(cond);
         return;
     }
 
+    pthread_mutex_lock(&win32_cond->mtx_broadcast);
+
     /* non-native condition variables */
     pthread_mutex_lock(&win32_cond->mtx_waiter_count);
-    if (win32_cond->waiter_count) {
+    have_waiter = win32_cond->waiter_count;
+    pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+
+    if (have_waiter) {
         ReleaseSemaphore(win32_cond->semaphore, 1, NULL);
-        win32_cond->waiter_count--;
+        WaitForSingleObject(win32_cond->waiters_done, INFINITE);
+        ResetEvent(win32_cond->waiters_done);
     }
-    pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
+
+    pthread_mutex_unlock(&win32_cond->mtx_broadcast);
 }
 
 static void w32thread_init(void)