[polypaudio-commits] r847 - /trunk/src/polyp/thread-mainloop.c

svnmailer-noreply at 0pointer.de svnmailer-noreply at 0pointer.de
Thu May 11 07:57:25 PDT 2006


Author: ossman
Date: Thu May 11 16:57:24 2006
New Revision: 847

URL: http://0pointer.de/cgi-bin/viewcvs.cgi?rev=847&root=polypaudio&view=rev
Log:
Windows support for the threaded API.

Modified:
    trunk/src/polyp/thread-mainloop.c

Modified: trunk/src/polyp/thread-mainloop.c
URL: http://0pointer.de/cgi-bin/viewcvs.cgi/trunk/src/polyp/thread-mainloop.c?rev=847&root=polypaudio&r1=846&r2=847&view=diff
==============================================================================
--- trunk/src/polyp/thread-mainloop.c (original)
+++ trunk/src/polyp/thread-mainloop.c Thu May 11 16:57:24 2006
@@ -37,58 +37,117 @@
 #include <pthread.h>
 #endif
 
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
 #include <polypcore/log.h>
 #include <polypcore/xmalloc.h>
+#include <polypcore/hashmap.h>
 
 #include "mainloop.h"
 #include "thread-mainloop.h"
 
-/* FIXME: Add defined(OS_IS_WIN32) when support is added */
-#if defined(HAVE_PTHREAD)
+#if defined(HAVE_PTHREAD) || defined(OS_IS_WIN32)
 
 struct pa_threaded_mainloop {
     pa_mainloop *real_mainloop;
+    int n_waiting;
+    int thread_running;
+
+#ifdef OS_IS_WIN32
+    DWORD thread_id;
+    HANDLE thread;
+    CRITICAL_SECTION mutex;
+    pa_hashmap *cond_events;
+    HANDLE accept_cond;
+#else
     pthread_t thread_id;
     pthread_mutex_t mutex;
-    int n_waiting;
     pthread_cond_t cond, accept_cond;
-    int thread_running;
+#endif
 };
 
+static inline int in_worker(pa_threaded_mainloop *m) {
+#ifdef OS_IS_WIN32
+    return GetCurrentThreadId() == m->thread_id;
+#else
+    return pthread_equal(pthread_self(), m->thread_id);
+#endif
+}
+
 static int poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) {
+#ifdef OS_IS_WIN32
+    CRITICAL_SECTION *mutex = userdata;
+#else
     pthread_mutex_t *mutex = userdata;
+#endif
+
     int r;
 
     assert(mutex);
-    
+
     /* Before entering poll() we unlock the mutex, so that
      * avahi_simple_poll_quit() can succeed from another thread. */
 
+#ifdef OS_IS_WIN32
+    LeaveCriticalSection(mutex);
+#else    
     pthread_mutex_unlock(mutex);
+#endif
+
     r = poll(ufds, nfds, timeout);
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(mutex);
+#else
     pthread_mutex_lock(mutex);
+#endif
 
     return r;
 }
 
-static void* thread(void *userdata){
+#ifdef OS_IS_WIN32
+static DWORD WINAPI thread(void *userdata) {
+#else
+static void* thread(void *userdata) {
+#endif
     pa_threaded_mainloop *m = userdata;
+
+#ifndef OS_IS_WIN32
     sigset_t mask;
 
     /* Make sure that signals are delivered to the main thread */
     sigfillset(&mask);
     pthread_sigmask(SIG_BLOCK, &mask, NULL);
-
+#endif
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(&m->mutex);
+#else
     pthread_mutex_lock(&m->mutex);
+#endif
+
     pa_mainloop_run(m->real_mainloop, NULL);
+
+#ifdef OS_IS_WIN32
+    LeaveCriticalSection(&m->mutex);
+#else
     pthread_mutex_unlock(&m->mutex);
-
+#endif
+
+#ifdef OS_IS_WIN32
+    return 0;
+#else
     return NULL;
+#endif
 }
 
 pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
     pa_threaded_mainloop *m;
+#ifndef OS_IS_WIN32
     pthread_mutexattr_t a;
+#endif
 
     m = pa_xnew(pa_threaded_mainloop, 1);
 
@@ -99,6 +158,14 @@
 
     pa_mainloop_set_poll_func(m->real_mainloop, poll_func, &m->mutex);
 
+#ifdef OS_IS_WIN32
+    InitializeCriticalSection(&m->mutex);
+
+    m->cond_events = pa_hashmap_new(NULL, NULL);
+    assert(m->cond_events);
+    m->accept_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
+    assert(m->accept_cond);
+#else
     pthread_mutexattr_init(&a);
     pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE);
     pthread_mutex_init(&m->mutex, &a);
@@ -106,6 +173,8 @@
     
     pthread_cond_init(&m->cond, NULL);
     pthread_cond_init(&m->accept_cond, NULL);
+#endif
+
     m->thread_running = 0;
     m->n_waiting = 0;
 
@@ -116,7 +185,7 @@
     assert(m);
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id));
+    assert(!m->thread_running || !in_worker(m));
 
     if (m->thread_running)
         pa_threaded_mainloop_stop(m);
@@ -124,9 +193,14 @@
     if (m->real_mainloop)
         pa_mainloop_free(m->real_mainloop);
 
+#ifdef OS_IS_WIN32
+    pa_hashmap_free(m->cond_events, NULL, NULL);
+    CloseHandle(m->accept_cond);
+#else
     pthread_mutex_destroy(&m->mutex);
     pthread_cond_destroy(&m->cond);
     pthread_cond_destroy(&m->accept_cond);
+#endif
     
     pa_xfree(m);
 }
@@ -135,6 +209,18 @@
     assert(m);
 
     assert(!m->thread_running);
+
+#ifdef OS_IS_WIN32
+
+    EnterCriticalSection(&m->mutex);
+
+    m->thread = CreateThread(NULL, 0, thread, m, 0, &m->thread_id);
+    if (!m->thread) {
+        LeaveCriticalSection(&m->mutex);
+        return -1;
+    }
+
+#else
 
     pthread_mutex_lock(&m->mutex);
 
@@ -143,9 +229,15 @@
         return -1;
     }
 
+#endif
+
     m->thread_running = 1;
     
+#ifdef OS_IS_WIN32
+    LeaveCriticalSection(&m->mutex);
+#else
     pthread_mutex_unlock(&m->mutex);
+#endif
 
     return 0;
 }
@@ -157,13 +249,29 @@
         return;
 
     /* Make sure that this function is not called from the helper thread */
-    assert(!pthread_equal(pthread_self(), m->thread_id));
-
+    assert(!in_worker(m));
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(&m->mutex);
+#else
     pthread_mutex_lock(&m->mutex);
+#endif
+
     pa_mainloop_quit(m->real_mainloop, 0);
+
+#ifdef OS_IS_WIN32
+    LeaveCriticalSection(&m->mutex);
+#else
     pthread_mutex_unlock(&m->mutex);
-
+#endif
+
+#ifdef OS_IS_WIN32
+    WaitForSingleObject(m->thread, INFINITE);
+    CloseHandle(m->thread);
+#else
     pthread_join(m->thread_id, NULL);
+#endif
+
     m->thread_running = 0;
 
     return;
@@ -173,37 +281,113 @@
     assert(m);
     
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id));
-
+    assert(!m->thread_running || !in_worker(m));
+
+#ifdef OS_IS_WIN32
+    EnterCriticalSection(&m->mutex);
+#else
     pthread_mutex_lock(&m->mutex);
+#endif
 }
 
 void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
     assert(m);
     
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id));
-
+    assert(!m->thread_running || !in_worker(m));
+
+#ifdef OS_IS_WIN32
+    LeaveCriticalSection(&m->mutex);
+#else
     pthread_mutex_unlock(&m->mutex);
+#endif
 }
 
 void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
-    assert(m);
-    
+#ifdef OS_IS_WIN32
+    void *iter;
+    const void *key;
+    HANDLE event;
+#endif
+
+    assert(m);
+
+#ifdef OS_IS_WIN32
+
+    iter = NULL;
+    while (1) {
+        pa_hashmap_iterate(m->cond_events, &iter, &key);
+        if (key == NULL)
+            break;
+        event = (HANDLE)pa_hashmap_get(m->cond_events, key);
+        SetEvent(event);
+    }
+
+#else
+
     pthread_cond_broadcast(&m->cond);
 
-    if (wait_for_accept && m->n_waiting > 0)
+#endif
+
+    if (wait_for_accept && m->n_waiting > 0) {
+
+#ifdef OS_IS_WIN32
+
+        /* This is just to make sure it's unsignaled */
+        WaitForSingleObject(m->accept_cond, 0);
+
+        LeaveCriticalSection(&m->mutex);
+
+        WaitForSingleObject(m->accept_cond, INFINITE);
+
+        EnterCriticalSection(&m->mutex);
+
+#else
+
         pthread_cond_wait(&m->accept_cond, &m->mutex);
+
+#endif
+
+    }
 }
 
 void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
-    assert(m);
-    
-    /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id));
+#ifdef OS_IS_WIN32
+    HANDLE event;
+    DWORD result;
+#endif
+
+    assert(m);
+    
+    /* Make sure that this function is not called from the helper thread */
+    assert(!m->thread_running || !in_worker(m));
 
     m->n_waiting ++;
+
+#ifdef OS_IS_WIN32
+
+    event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    assert(event);
+
+    pa_hashmap_put(m->cond_events, event, event);
+
+    LeaveCriticalSection(&m->mutex);
+
+    result = WaitForSingleObject(event, INFINITE);
+    assert(result == WAIT_OBJECT_0);
+
+    EnterCriticalSection(&m->mutex);
+
+    pa_hashmap_remove(m->cond_events, event);
+
+    CloseHandle(event);
+
+#else
+
     pthread_cond_wait(&m->cond, &m->mutex);
+
+#endif
+
     assert(m->n_waiting > 0);
     m->n_waiting --;
 }
@@ -212,9 +396,13 @@
     assert(m);
     
     /* Make sure that this function is not called from the helper thread */
-    assert(!m->thread_running || !pthread_equal(pthread_self(), m->thread_id));
-
+    assert(!m->thread_running || !in_worker(m));
+
+#ifdef OS_IS_WIN32
+    SetEvent(m->accept_cond);
+#else
     pthread_cond_signal(&m->accept_cond);
+#endif
 }
 
 int pa_threaded_mainloop_get_retval(pa_threaded_mainloop *m) {




More information about the pulseaudio-commits mailing list