#ifndef NALL_THREAD_HPP #define NALL_THREAD_HPP #include #include #include #if defined(PLATFORM_X) || defined(PLATFORM_OSX) #include namespace nall { inline void* thread_entry_point(void*); struct thread { thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { initialize(); pthread_create(&pthread, nullptr, thread_entry_point, (void*)this); } ~thread() { join(); } bool active() const { return completed == false; } void join() { if(dead) return; dead = true; pthread_join(pthread, nullptr); } static bool primary() { initialize(); return pthread_equal(primaryThread(), pthread_self()); } private: pthread_t pthread; function entryPoint; volatile bool completed, dead; friend void* thread_entry_point(void*); static void initialize() { static bool initialized = false; if(initialized) return; initialized = true; primaryThread() = pthread_self(); } static pthread_t& primaryThread() { static pthread_t thread; return thread; } }; void* thread_entry_point(void* parameter) { thread* context = (thread*)parameter; context->entryPoint(); context->completed = true; pthread_exit(nullptr); } } #elif defined(PLATFORM_WIN) namespace nall { inline DWORD WINAPI thread_entry_point(LPVOID); struct thread { thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { initialize(); hthread = CreateThread(nullptr, 0, thread_entry_point, (void*)this, 0, nullptr); } ~thread() { join(); } bool active() const { return completed == false; } void join() { if(dead) return; dead = true; WaitForSingleObject(hthread, INFINITE); CloseHandle(hthread); } static bool primary() { initialize(); return primaryThread() == GetCurrentThreadId(); } private: HANDLE hthread; function entryPoint; volatile bool completed, dead; friend DWORD WINAPI thread_entry_point(LPVOID); static void initialize() { static bool initialized = false; if(initialized) return; initialized = true; primaryThread() = GetCurrentThreadId(); } static DWORD& primaryThread() { static DWORD thread; return thread; } }; inline DWORD WINAPI thread_entry_point(LPVOID parameter) { thread *context = (thread*)parameter; context->entryPoint(); context->completed = true; return 0; } } #endif #endif