/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #if __PLATFORM_WINDOWS__ #define WIN32_LEAN_AND_MEAN #include #include #elif __PLATFORM_POSIX__ #include #endif #include #include "thread/thread.h" #include "assert/nassert.h" #include "log/log.h" #include #include #if __PLATFORM_WINDOWS__ namespace GS { namespace Threading { //------------------------------------------------------------------------------ static unsigned __stdcall win32_thread_entrypoint(void *parm) { Thread *t = (Thread *)parm; __ASSERT__(t != NULL); t->Execute(); return 1; } void Thread::Join() { if (handle != 0) { WaitForSingleObject((HANDLE)handle, INFINITE); CloseHandle((HANDLE)handle); handle = 0; } } bool Thread::Start() { handle = (void *)_beginthreadex(NULL, 0, &win32_thread_entrypoint, (void *)this, 0, NULL); return handle != 0; } bool Thread::SetPriority(int) { return false; } void Thread::Kill() { if (handle != 0) { CloseHandle((HANDLE)handle); handle = 0; } } void Thread::SetName(const char *name) { if (name == nullptr) return; // Conversion UTF-8 (ou ANSI selon votre projet) vers UTF-16 int length = MultiByteToWideChar(CP_UTF8, 0, name, -1, nullptr, 0); if (length == 0) return; std::wstring wname(length, L'\0'); MultiByteToWideChar(CP_UTF8, 0, name, -1, &wname[0], length); SetThreadDescription(GetCurrentThread(), wname.c_str()); } void Thread::Switch() { SwitchToThread(); } Thread::Thread() { handle = 0; } Thread::~Thread() { Kill(); } } } //------------------------------------------------------------------------------ #elif __PLATFORM_EMSCRIPTEN__ namespace GS { namespace Threading { //------------------------------------------------------------------------------ void *pthread_execute(void *parm) { return NULL; } void Thread::Join() {} bool Thread::Start() { return false; } bool Thread::SetPriority(int priority) { return false; } void Thread::Kill() {} void Thread::SetName(const char *) {} void Thread::Switch() {} Thread::Thread() {} Thread::~Thread() {} } } //------------------------------------------------------------------------------ #elif __PLATFORM_POSIX__ namespace GS { namespace Threading { //------------------------------------------------------------------------------ void *pthread_execute(void *parm) { Thread *t = (Thread * const)parm; t->Execute(); return NULL; } void Thread::Join() { pthread_join(*((pthread_t *)handle), NULL); } bool Thread::Start() { if (!(handle = (void *)new pthread_t)) return false; return pthread_create((pthread_t *)handle, NULL, pthread_execute, this) == 0; } bool Thread::SetPriority(int priority) { #ifdef EMSCRIPTEN return false; #else if (!handle) return false; sched_param param; memset(¶m, 0, sizeof(param)); param.sched_priority = priority; return asbool(pthread_setschedparam(*((pthread_t *)handle), SCHED_OTHER, ¶m) == 0); #endif } void Thread::Kill() { #if __PLATFORM_ANDROID_NDK__ __ASSERT_MSG__(true, "Android NDK cannot kill a thread."); #else if (handle) pthread_cancel(*((pthread_t *)handle)); delete (pthread_t *)handle; handle = NULL; #endif } void Thread::SetName(const char *) {} void Thread::Switch() { sched_yield(); } Thread::Thread() { handle = NULL; } Thread::~Thread() { delete (pthread_t *)handle; } } } //------------------------------------------------------------------------------ #elif __PLATFORM_NINTENDO_WII__ namespace GS { namespace Threading { //------------------------------------------------------------------------------ void *__OSthread_wii_execute(void *parm) { nThread *t = (nThread * const)parm; t->alive.Set(1); return (void *)(t->Execute() ? 1 : 0); } void Thread::Join() { void *rv; if (alive.Get()) OSJoinThread(&thread, &rv); alive.Set(0); } void Thread::Resume() { if (alive.Get()) OSResumeThread(&thread); } void Thread::Suspend() { if (alive.Get()) OSSuspendThread(&thread); } bool Thread::Start() { return OSCreateThread(&thread, &__OSthread_wii_execute, this, thread_stack + 32768, 32768, 20, 0); } bool Thread::SetPriority(int priority) { return alive.Get() ? OSSetThreadPriority(&thread, priority) : false; } void Thread::Kill() { if (alive.Get()) OSCancelThread(&thread); alive.Set(0); } void Thread::SetName(const char *) {} Thread::Thread() {} Thread::~Thread() { Kill(); } //------------------------------------------------------------------------------ } } #endif