]> git.cworth.org Git - apitrace/commitdiff
Implement missing threading primitive for Windows.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 23 Oct 2012 19:15:36 +0000 (20:15 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 23 Oct 2012 19:15:36 +0000 (20:15 +0100)
CMakeLists.txt
common/os_thread.hpp
common/os_workqueue.hpp
common/workqueue.cpp [new file with mode: 0644]
common/workqueue_posix.cpp [deleted file]
common/workqueue_win32.cpp [deleted file]

index a4f01fb573d43d356148c120be0371948ea8ce7b..6329689d614fe5a809ecaa6046945b044707c1de 100644 (file)
@@ -272,10 +272,8 @@ include_directories (
 if (WIN32)
     set (os os_win32.cpp)
     set (glws_os glws_wgl.cpp)
-    set (workqueue workqueue_win32.cpp)
 else ()
     set (os os_posix.cpp)
-    set (workqueue workqueue_posix.cpp)
     if (APPLE)
         set (glws_os glws_cocoa.mm)
     else ()
@@ -306,7 +304,7 @@ add_library (common STATIC
     common/image_pnm.cpp
     common/image_png.cpp
     common/${os}
-    common/${workqueue}
+    common/workqueue.cpp
 )
 
 set_target_properties (common PROPERTIES
index 9d6a9891524564803d844bfe923de13dfd8442c0..72195b6c2aecbae33517904b75845fc9e1cdc10d 100644 (file)
@@ -187,14 +187,14 @@ namespace os {
     {
     public:
 #ifdef _WIN32
-        /* FIXME */
+        typedef CONDITION_VARIABLE native_handle_type;
 #else
         typedef pthread_cond_t native_handle_type;
 #endif
 
         condition_variable() {
 #ifdef _WIN32
-            /* FIXME */
+            InitializeConditionVariable(&_native_handle);
 #else
             pthread_cond_init(&_native_handle, NULL);
 #endif
@@ -202,7 +202,7 @@ namespace os {
 
         ~condition_variable() {
 #ifdef _WIN32
-            /* FIXME */
+            /* No-op */
 #else
             pthread_cond_destroy(&_native_handle);
 #endif
@@ -211,7 +211,7 @@ namespace os {
         inline void
         signal(void) {
 #ifdef _WIN32
-            /* FIXME */
+            WakeConditionVariable(&_native_handle);
 #else
             pthread_cond_signal(&_native_handle);
 #endif
@@ -219,10 +219,12 @@ namespace os {
 
         inline void
         wait(unique_lock<mutex> & lock) {
+            mutex::native_handle_type & mutex_native_handle = lock.mutex()->native_handle();
 #ifdef _WIN32
             /* FIXME */
+            SleepConditionVariableCS(&_native_handle, &mutex_native_handle, INFINITE);
 #else
-            pthread_cond_wait(&_native_handle, &lock.mutex()->native_handle());
+            pthread_cond_wait(&_native_handle, &mutex_native_handle);
 #endif
         }
 
@@ -305,7 +307,7 @@ namespace os {
     class thread {
     public:
 #ifdef _WIN32
-        /* FIXME */
+        typedef HANDLE native_handle_type;
 #else
         typedef pthread_t native_handle_type;
 #endif
@@ -314,6 +316,8 @@ namespace os {
         explicit thread( Function& f, Arg & arg ) {
 #ifdef _WIN32
             /* FIXME */
+            DWORD id = 0;
+            _native_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)f, (LPVOID)arg, 0, &id);
 #else
             pthread_create(&_native_handle, NULL, f, arg);
 #endif
@@ -322,7 +326,7 @@ namespace os {
         inline void
         join() {
 #ifdef _WIN32
-            /* FIXME */
+            WaitForSingleObject(_native_handle, INFINITE);
 #else
             pthread_join(_native_handle, NULL);
 #endif
@@ -330,6 +334,16 @@ namespace os {
 
     private:
         native_handle_type _native_handle;
+
+#if 0
+#ifdef _WIN32
+        template< class Function, class Arg >
+        static DWORD WINAPI
+        ThreadProc(LPVOID lpParameter) {
+
+        );
+#endif
+#endif
     };
 
 } /* namespace os */
index f8ab84c66cb3437a78e32883d435b62e31401298..047d3dbb4125967f72a83cad68015b30e180aea3 100644 (file)
@@ -19,9 +19,6 @@ public:
     virtual ~WorkQueueWork(void) { }
 };
 
-extern "C"
-void *WorkQueue__entry_thunk(void *data);
-
 class WorkQueue {
     std::queue<WorkQueueWork *> work_queue;
 
@@ -35,10 +32,9 @@ class WorkQueue {
     os::thread thread;
 
     void wake_up_thread(void);
-    void thread_entry(void);
     int run_tasks(void);
-    friend void *WorkQueue__entry_thunk(void *data);
 public:
+    void thread_entry(void);
     void queue_work(WorkQueueWork *work);
     void flush(void);
     void destroy(void);
diff --git a/common/workqueue.cpp b/common/workqueue.cpp
new file mode 100644 (file)
index 0000000..fcd697a
--- /dev/null
@@ -0,0 +1,118 @@
+#include <queue>
+#include <assert.h>
+
+#include "os_workqueue.hpp"
+
+namespace os
+{
+
+/**
+ * return 0 on batch complete, -1 on thread exit request.
+ */
+int WorkQueue::run_tasks(void)
+{
+    os::unique_lock<os::mutex> lock(mutex);
+
+    while (work_queue.empty() && !exit_workqueue) {
+        wake_cond.wait(lock);
+    }
+
+    if (exit_workqueue) {
+        return -1;
+    }
+
+    std::queue<WorkQueueWork *> batch;
+    std::swap(work_queue, batch);
+    busy = true;
+
+    lock.unlock();
+
+    assert(!batch.empty());
+    while (!batch.empty()) {
+        WorkQueueWork *task;
+
+        task = batch.front();
+        task->run();
+        batch.pop();
+        delete task;
+    }
+
+    lock.lock();
+
+    busy = false;
+    complete_cond.signal();
+
+    return 0;
+}
+
+/* Must be called with WorkQueue::lock held */
+void WorkQueue::wake_up_thread(void)
+{
+    wake_cond.signal();
+}
+
+void WorkQueue::queue_work(WorkQueueWork *task)
+{
+    mutex.lock();
+    work_queue.push(task);
+    wake_up_thread();
+    mutex.unlock();
+}
+
+void WorkQueue::flush(void)
+{
+    os::unique_lock<os::mutex> lock(mutex);
+    while (!work_queue.empty() || busy) {
+        complete_cond.wait(lock);
+    }
+}
+
+void WorkQueue::thread_entry(void)
+{
+    int err;
+
+    do {
+        err = run_tasks();
+    } while (!err);
+}
+
+void WorkQueue::destroy(void)
+{
+    mutex.lock();
+    exit_workqueue = true;
+    wake_up_thread();
+    mutex.unlock();
+}
+
+static
+#ifdef _WIN32
+DWORD WINAPI
+#else
+void *
+#endif
+WorkQueue__entry_thunk(void *data)
+{
+    WorkQueue *thread = static_cast<WorkQueue *>(data);
+
+    thread->thread_entry();
+
+#ifdef _WIN32
+    return 0;
+#else
+    return NULL;
+#endif
+}
+
+WorkQueue::WorkQueue(void) :
+    busy(false),
+    exit_workqueue(false),
+    thread(WorkQueue__entry_thunk, this)
+{
+}
+
+WorkQueue::~WorkQueue(void)
+{
+    thread.join();
+}
+
+}
diff --git a/common/workqueue_posix.cpp b/common/workqueue_posix.cpp
deleted file mode 100644 (file)
index 7df7e54..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-#include <queue>
-#include <assert.h>
-
-#include "os_workqueue.hpp"
-
-namespace os
-{
-
-/**
- * return 0 on batch complete, -1 on thread exit request.
- */
-int WorkQueue::run_tasks(void)
-{
-    os::unique_lock<os::mutex> lock(mutex);
-
-    while (work_queue.empty() && !exit_workqueue) {
-        wake_cond.wait(lock);
-    }
-
-    if (exit_workqueue) {
-        return -1;
-    }
-
-    std::queue<WorkQueueWork *> batch;
-    std::swap(work_queue, batch);
-    busy = true;
-
-    lock.unlock();
-
-    assert(!batch.empty());
-    while (!batch.empty()) {
-        WorkQueueWork *task;
-
-        task = batch.front();
-        task->run();
-        batch.pop();
-        delete task;
-    }
-
-    lock.lock();
-
-    busy = false;
-    complete_cond.signal();
-
-    return 0;
-}
-
-/* Must be called with WorkQueue::lock held */
-void WorkQueue::wake_up_thread(void)
-{
-    wake_cond.signal();
-}
-
-void WorkQueue::queue_work(WorkQueueWork *task)
-{
-    mutex.lock();
-    work_queue.push(task);
-    wake_up_thread();
-    mutex.unlock();
-}
-
-void WorkQueue::flush(void)
-{
-    os::unique_lock<os::mutex> lock(mutex);
-    while (!work_queue.empty() || busy) {
-        complete_cond.wait(lock);
-    }
-}
-
-void WorkQueue::thread_entry(void)
-{
-    int err;
-
-    do {
-        err = run_tasks();
-    } while (!err);
-}
-
-void WorkQueue::destroy(void)
-{
-    mutex.lock();
-    exit_workqueue = true;
-    wake_up_thread();
-    mutex.unlock();
-}
-
-void *WorkQueue__entry_thunk(void *data)
-{
-    WorkQueue *thread = static_cast<WorkQueue *>(data);
-
-    thread->thread_entry();
-
-    return NULL;
-}
-
-WorkQueue::WorkQueue(void) :
-    busy(false),
-    exit_workqueue(false),
-    thread(WorkQueue__entry_thunk, this)
-{
-}
-
-WorkQueue::~WorkQueue(void)
-{
-    thread.join();
-}
-
-}
diff --git a/common/workqueue_win32.cpp b/common/workqueue_win32.cpp
deleted file mode 100644 (file)
index 3c1b9cd..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <queue>
-#include <assert.h>
-
-#include "os.hpp"
-#include "os_workqueue.hpp"
-
-namespace os
-{
-
-/**
- * return 0 on batch complete, -1 on thread exit request.
- */
-int WorkQueue::run_tasks(void)
-{
-    return 0;
-}
-
-void WorkQueue::queue_work(WorkQueueWork *task)
-{
-    task->run();
-}
-
-void WorkQueue::flush(void)
-{
-}
-
-void WorkQueue::destroy(void)
-{
-}
-
-WorkQueue::WorkQueue(void) :
-       busy(false), exit_workqueue(false)
-{
-    static bool warned;
-
-    if (!warned) {
-        warned = true;
-        os::log("%s: no workqueue implementation, running in single-threaded mode\n",
-                __func__);
-    }
-}
-
-WorkQueue::~WorkQueue(void)
-{
-}
-
-}