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 ()
common/image_pnm.cpp
common/image_png.cpp
common/${os}
- common/${workqueue}
+ common/workqueue.cpp
)
set_target_properties (common PROPERTIES
{
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
~condition_variable() {
#ifdef _WIN32
- /* FIXME */
+ /* No-op */
#else
pthread_cond_destroy(&_native_handle);
#endif
inline void
signal(void) {
#ifdef _WIN32
- /* FIXME */
+ WakeConditionVariable(&_native_handle);
#else
pthread_cond_signal(&_native_handle);
#endif
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
}
class thread {
public:
#ifdef _WIN32
- /* FIXME */
+ typedef HANDLE native_handle_type;
#else
typedef pthread_t native_handle_type;
#endif
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
inline void
join() {
#ifdef _WIN32
- /* FIXME */
+ WaitForSingleObject(_native_handle, INFINITE);
#else
pthread_join(_native_handle, NULL);
#endif
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 */
virtual ~WorkQueueWork(void) { }
};
-extern "C"
-void *WorkQueue__entry_thunk(void *data);
-
class WorkQueue {
std::queue<WorkQueueWork *> work_queue;
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);
--- /dev/null
+#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();
+}
+
+}
+++ /dev/null
-#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();
-}
-
-}
+++ /dev/null
-#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)
-{
-}
-
-}