aboutsummaryrefslogtreecommitdiff
path: root/dep/src/g3dlite/GThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/src/g3dlite/GThread.cpp')
-rw-r--r--dep/src/g3dlite/GThread.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/dep/src/g3dlite/GThread.cpp b/dep/src/g3dlite/GThread.cpp
new file mode 100644
index 00000000000..607e4b3572f
--- /dev/null
+++ b/dep/src/g3dlite/GThread.cpp
@@ -0,0 +1,229 @@
+/**
+ @file GThread.cpp
+
+ GThread class.
+
+ @created 2005-09-24
+ @edited 2005-10-22
+ */
+
+#include "G3D/GThread.h"
+#include "G3D/System.h"
+#include "G3D/debugAssert.h"
+#include "G3D/GMutex.h"
+
+namespace G3D {
+
+namespace _internal {
+
+class BasicThread: public GThread {
+public:
+ BasicThread(const std::string& name, void (*proc)(void*), void* param):
+ GThread(name), m_wrapperProc(proc), m_param(param) { }
+protected:
+ virtual void threadMain() {
+ m_wrapperProc(m_param);
+ }
+
+private:
+ void (*m_wrapperProc)(void*);
+
+ void* m_param;
+};
+
+} // namespace _internal
+
+
+GThread::GThread(const std::string& name):
+ m_status(STATUS_CREATED),
+ m_name(name) {
+
+#ifdef G3D_WIN32
+ m_event = NULL;
+#endif
+
+ // system-independent clear of handle
+ System::memset(&m_handle, 0, sizeof(m_handle));
+}
+
+GThread::~GThread() {
+#ifdef _MSC_VER
+# pragma warning( push )
+# pragma warning( disable : 4127 )
+#endif
+ alwaysAssertM(m_status != STATUS_RUNNING, "Deleting thread while running.");
+#ifdef _MSC_VER
+# pragma warning( pop )
+#endif
+
+#ifdef G3D_WIN32
+ if (m_event) {
+ ::CloseHandle(m_event);
+ }
+#endif
+}
+
+GThreadRef GThread::create(const std::string& name, void (*proc)(void*), void* param) {
+ return new _internal::BasicThread(name, proc, param);
+}
+
+
+bool GThread::started() const {
+ return m_status != STATUS_CREATED;
+}
+
+bool GThread::start(SpawnBehavior behavior) {
+
+ debugAssertM(! started(), "Thread has already executed.");
+ if (started()) {
+ return false;
+ }
+
+ m_status = STATUS_STARTED;
+
+ if (behavior == USE_CURRENT_THREAD) {
+ // Run on this thread
+ m_status = STATUS_RUNNING;
+ threadMain();
+ m_status = STATUS_COMPLETED;
+ return true;
+ }
+
+# ifdef G3D_WIN32
+ DWORD threadId;
+
+ m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ debugAssert(m_event);
+
+ m_handle = ::CreateThread(NULL, 0, &internalThreadProc, this, 0, &threadId);
+
+ if (m_handle == NULL) {
+ ::CloseHandle(m_event);
+ m_event = NULL;
+ }
+
+ return (m_handle != NULL);
+# else
+ if (!pthread_create(&m_handle, NULL, &internalThreadProc, this)) {
+ return true;
+ } else {
+ // system-independent clear of handle
+ System::memset(&m_handle, 0, sizeof(m_handle));
+
+ return false;
+ }
+# endif
+}
+
+void GThread::terminate() {
+ if (m_handle) {
+# ifdef G3D_WIN32
+ ::TerminateThread(m_handle, 0);
+# else
+ pthread_kill(m_handle, SIGSTOP);
+# endif
+ // system-independent clear of handle
+ System::memset(&m_handle, 0, sizeof(m_handle));
+ }
+}
+
+
+bool GThread::running() const{
+ return (m_status == STATUS_RUNNING);
+}
+
+
+bool GThread::completed() const {
+ return (m_status == STATUS_COMPLETED);
+}
+
+
+void GThread::waitForCompletion() {
+ if (m_status == STATUS_COMPLETED) {
+ // Must be done
+ return;
+ }
+
+# ifdef G3D_WIN32
+ debugAssert(m_event);
+ ::WaitForSingleObject(m_event, INFINITE);
+# else
+ debugAssert(m_handle);
+ pthread_join(m_handle, NULL);
+# endif
+}
+
+
+#ifdef G3D_WIN32
+DWORD WINAPI GThread::internalThreadProc(LPVOID param) {
+ GThread* current = reinterpret_cast<GThread*>(param);
+ debugAssert(current->m_event);
+ current->m_status = STATUS_RUNNING;
+ current->threadMain();
+ current->m_status = STATUS_COMPLETED;
+ ::SetEvent(current->m_event);
+ return 0;
+}
+#else
+void* GThread::internalThreadProc(void* param) {
+ GThread* current = reinterpret_cast<GThread*>(param);
+ current->m_status = STATUS_RUNNING;
+ current->threadMain();
+ current->m_status = STATUS_COMPLETED;
+ return (void*)NULL;
+}
+#endif
+
+
+
+//GMutex implementation
+GMutex::GMutex() {
+#ifdef G3D_WIN32
+ ::InitializeCriticalSection(&m_handle);
+#else
+ int ret = pthread_mutexattr_init(&m_attr);
+ debugAssert(ret == 0);
+ ret = pthread_mutexattr_settype(&m_attr, PTHREAD_MUTEX_RECURSIVE);
+ debugAssert(ret == 0);
+ ret = pthread_mutex_init(&m_handle, &m_attr);
+ debugAssert(ret == 0);
+#endif
+}
+
+GMutex::~GMutex() {
+ //TODO: Debug check for locked
+#ifdef G3D_WIN32
+ ::DeleteCriticalSection(&m_handle);
+#else
+ int ret = pthread_mutex_destroy(&m_handle);
+ debugAssert(ret == 0);
+ ret = pthread_mutexattr_destroy(&m_attr);
+ debugAssert(ret == 0);
+#endif
+}
+
+bool GMutex::tryLock() {
+#ifdef G3D_WIN32
+ return (::TryEnterCriticalSection(&m_handle) != 0);
+#else
+ return (pthread_mutex_trylock(&m_handle) == 0);
+#endif
+}
+
+void GMutex::lock() {
+#ifdef G3D_WIN32
+ ::EnterCriticalSection(&m_handle);
+#else
+ pthread_mutex_lock(&m_handle);
+#endif
+}
+
+void GMutex::unlock() {
+#ifdef G3D_WIN32
+ ::LeaveCriticalSection(&m_handle);
+#else
+ pthread_mutex_unlock(&m_handle);
+#endif
+}
+
+} // namespace G3D