aboutsummaryrefslogtreecommitdiff
path: root/odb/details/win32/thread.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/details/win32/thread.cxx')
-rw-r--r--odb/details/win32/thread.cxx91
1 files changed, 91 insertions, 0 deletions
diff --git a/odb/details/win32/thread.cxx b/odb/details/win32/thread.cxx
new file mode 100644
index 0000000..610980d
--- /dev/null
+++ b/odb/details/win32/thread.cxx
@@ -0,0 +1,91 @@
+// file : odb/details/win32/thread.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <windows.h>
+#include <process.h> // _beginthreadex, _endthreadex
+
+#include <memory> // std::auto_ptr
+
+#include <odb/details/win32/thread.hxx>
+#include <odb/details/win32/exceptions.hxx>
+
+unsigned int __stdcall
+odb_thread_thunk (void* arg)
+{
+ odb::details::thread::thread_thunk (arg);
+ _endthreadex (0);
+ return 0;
+}
+
+namespace odb
+{
+ namespace details
+ {
+ void thread::
+ thread_thunk (void* arg)
+ {
+ data* d (static_cast<data*> (arg));
+ d->ret = d->func (d->arg);
+ d->mutex.lock ();
+ unsigned char count = --d->count;
+ d->mutex.unlock ();
+
+ if (count == 0)
+ delete d;
+ }
+
+ thread::
+ ~thread ()
+ {
+ if (handle_ != 0)
+ {
+ CloseHandle (handle_);
+
+ // Win32 mutex implementation does not throw.
+ //
+ data_->mutex.lock ();
+ unsigned char count = --data_->count;
+ data_->mutex.unlock ();
+
+ if (count == 0)
+ delete data_;
+ }
+ }
+
+ thread::
+ thread (void* (*func) (void*), void* arg)
+ {
+ std::auto_ptr<data> d (new data);
+ d->func = func;
+ d->arg = arg;
+ d->count = 2; // One for the thread and one for us.
+
+ handle_ = (HANDLE)_beginthreadex (
+ 0, 0, &odb_thread_thunk, d.get (), 0, 0);
+
+ if (handle_ == 0)
+ throw win32_exception ();
+
+ data_ = d.release ();
+ }
+
+ void* thread::
+ join ()
+ {
+ void* r;
+
+ if (WaitForSingleObject (handle_, INFINITE) != 0)
+ throw win32_exception ();
+
+ r = data_->ret;
+
+ CloseHandle (handle_);
+ delete data_;
+ handle_ = 0;
+ data_ = 0;
+ return r;
+ }
+ }
+}