summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bx/src/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bx/src/thread.cpp')
-rw-r--r--3rdparty/bx/src/thread.cpp226
1 files changed, 174 insertions, 52 deletions
diff --git a/3rdparty/bx/src/thread.cpp b/3rdparty/bx/src/thread.cpp
index fea7e8b606c..70ea4a0ecbe 100644
--- a/3rdparty/bx/src/thread.cpp
+++ b/3rdparty/bx/src/thread.cpp
@@ -5,24 +5,94 @@
#include <bx/thread.h>
+#if BX_PLATFORM_ANDROID \
+ || BX_PLATFORM_LINUX \
+ || BX_PLATFORM_NACL \
+ || BX_PLATFORM_IOS \
+ || BX_PLATFORM_OSX \
+ || BX_PLATFORM_PS4 \
+ || BX_PLATFORM_RPI
+# include <pthread.h>
+# if defined(__FreeBSD__)
+# include <pthread_np.h>
+# endif
+# if BX_PLATFORM_LINUX && (BX_CRT_GLIBC < 21200)
+# include <sys/prctl.h>
+# endif // BX_PLATFORM_
+#elif BX_PLATFORM_WINDOWS \
+ || BX_PLATFORM_WINRT \
+ || BX_PLATFORM_XBOX360 \
+ || BX_PLATFORM_XBOXONE
+# include <windows.h>
+# include <limits.h>
+# include <errno.h>
+# if BX_PLATFORM_WINRT
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::System::Threading;
+# endif // BX_PLATFORM_WINRT
+#endif // BX_PLATFORM_
+
#if BX_CONFIG_SUPPORTS_THREADING
namespace bx
{
- Thread::Thread()
-#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
- : m_handle(INVALID_HANDLE_VALUE)
- , m_threadId(UINT32_MAX)
+ struct ThreadInternal
+ {
+#if BX_PLATFORM_WINDOWS \
+ || BX_PLATFORM_WINRT \
+ || BX_PLATFORM_XBOX360 \
+ || BX_PLATFORM_XBOXONE
+ static DWORD WINAPI threadFunc(LPVOID _arg);
+ HANDLE m_handle;
+ DWORD m_threadId;
#elif BX_PLATFORM_POSIX
- : m_handle(0)
+ static void* threadFunc(void* _arg);
+ pthread_t m_handle;
+#endif // BX_PLATFORM_
+ };
+
+#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
+ DWORD WINAPI ThreadInternal::threadFunc(LPVOID _arg)
+ {
+ Thread* thread = (Thread*)_arg;
+ int32_t result = thread->entry();
+ return result;
+ }
+#else
+ void* ThreadInternal::threadFunc(void* _arg)
+ {
+ Thread* thread = (Thread*)_arg;
+ union
+ {
+ void* ptr;
+ int32_t i;
+ } cast;
+ cast.i = thread->entry();
+ return cast.ptr;
+ }
#endif // BX_PLATFORM_
- , m_fn(NULL)
+
+ Thread::Thread()
+ : m_fn(NULL)
, m_userData(NULL)
, m_stackSize(0)
, m_exitCode(0 /*EXIT_SUCCESS*/)
, m_running(false)
- {
- }
+ {
+ BX_STATIC_ASSERT(sizeof(ThreadInternal) <= sizeof(m_internal) );
+
+ ThreadInternal* ti = (ThreadInternal*)m_internal;
+#if BX_PLATFORM_WINDOWS \
+ || BX_PLATFORM_WINRT \
+ || BX_PLATFORM_XBOX360 \
+ || BX_PLATFORM_XBOXONE
+ ti->m_handle = INVALID_HANDLE_VALUE;
+ ti->m_threadId = UINT32_MAX;
+#elif BX_PLATFORM_POSIX
+ ti->m_handle = 0;
+#endif // BX_PLATFORM_
+ }
Thread::~Thread()
{
@@ -41,21 +111,24 @@ namespace bx
m_stackSize = _stackSize;
m_running = true;
+ ThreadInternal* ti = (ThreadInternal*)m_internal;
#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE
- m_handle = ::CreateThread(NULL
+ ti->m_handle = ::CreateThread(NULL
, m_stackSize
- , (LPTHREAD_START_ROUTINE)threadFunc
+ , (LPTHREAD_START_ROUTINE)ti->threadFunc
, this
, 0
, NULL
);
#elif BX_PLATFORM_WINRT
- m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
+ ti->m_handle = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
auto workItemHandler = ref new WorkItemHandler([=](IAsyncAction^)
- {
- m_exitCode = threadFunc(this);
- SetEvent(m_handle);
- }, CallbackContext::Any);
+ {
+ m_exitCode = ti->threadFunc(this);
+ SetEvent(ti->m_handle);
+ }
+ , CallbackContext::Any
+ );
ThreadPool::RunAsync(workItemHandler, WorkItemPriority::Normal, WorkItemOptions::TimeSliced);
#elif BX_PLATFORM_POSIX
@@ -72,12 +145,7 @@ namespace bx
BX_CHECK(0 == result, "pthread_attr_setstacksize failed! %d", result);
}
- // sched_param sched;
- // sched.sched_priority = 0;
- // result = pthread_attr_setschedparam(&attr, &sched);
- // BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result);
-
- result = pthread_create(&m_handle, &attr, &threadFunc, this);
+ result = pthread_create(&ti->m_handle, &attr, &ti->threadFunc, this);
BX_CHECK(0 == result, "pthread_attr_setschedparam failed! %d", result);
#else
# error "Not implemented!"
@@ -94,25 +162,27 @@ namespace bx
void Thread::shutdown()
{
BX_CHECK(m_running, "Not running!");
+ ThreadInternal* ti = (ThreadInternal*)m_internal;
#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360
- WaitForSingleObject(m_handle, INFINITE);
- GetExitCodeThread(m_handle, (DWORD*)&m_exitCode);
- CloseHandle(m_handle);
- m_handle = INVALID_HANDLE_VALUE;
-#elif BX_PLATFORM_WINRT
- WaitForSingleObjectEx(m_handle, INFINITE, FALSE);
- CloseHandle(m_handle);
- m_handle = INVALID_HANDLE_VALUE;
+ WaitForSingleObject(ti->m_handle, INFINITE);
+ GetExitCodeThread(ti->m_handle, (DWORD*)&m_exitCode);
+ CloseHandle(ti->m_handle);
+ ti->m_handle = INVALID_HANDLE_VALUE;
+#elif BX_PLATFORM_WINRT || BX_PLATFORM_XBOXONE
+ WaitForSingleObjectEx(ti->m_handle, INFINITE, FALSE);
+ CloseHandle(ti->m_handle);
+ ti->m_handle = INVALID_HANDLE_VALUE;
#elif BX_PLATFORM_POSIX
union
{
void* ptr;
int32_t i;
} cast;
- pthread_join(m_handle, &cast.ptr);
+ pthread_join(ti->m_handle, &cast.ptr);
m_exitCode = cast.i;
- m_handle = 0;
+ ti->m_handle = 0;
#endif // BX_PLATFORM_
+
m_running = false;
}
@@ -128,17 +198,19 @@ namespace bx
void Thread::setThreadName(const char* _name)
{
+ ThreadInternal* ti = (ThreadInternal*)m_internal;
+ BX_UNUSED(ti);
#if BX_PLATFORM_OSX || BX_PLATFORM_IOS
pthread_setname_np(_name);
#elif (BX_CRT_GLIBC >= 21200) && ! BX_PLATFORM_HURD
- pthread_setname_np(m_handle, _name);
+ pthread_setname_np(ti->m_handle, _name);
#elif BX_PLATFORM_LINUX
prctl(PR_SET_NAME,_name, 0, 0, 0);
#elif BX_PLATFORM_BSD
# ifdef __NetBSD__
- pthread_setname_np(m_handle, "%s", (void*)_name);
+ pthread_setname_np(ti->m_handle, "%s", (void*)_name);
# else
- pthread_set_name_np(m_handle, _name);
+ pthread_set_name_np(ti->m_handle, _name);
# endif // __NetBSD__
#elif BX_PLATFORM_WINDOWS && BX_COMPILER_MSVC
# pragma pack(push, 8)
@@ -153,7 +225,7 @@ namespace bx
ThreadName tn;
tn.type = 0x1000;
tn.name = _name;
- tn.id = m_threadId;
+ tn.id = ti->m_threadId;
tn.flags = 0;
__try
@@ -175,33 +247,83 @@ namespace bx
int32_t Thread::entry()
{
#if BX_PLATFORM_WINDOWS
- m_threadId = ::GetCurrentThreadId();
+ ThreadInternal* ti = (ThreadInternal*)m_internal;
+ ti->m_threadId = ::GetCurrentThreadId();
#endif // BX_PLATFORM_WINDOWS
m_sem.post();
return m_fn(m_userData);
}
-#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
- DWORD WINAPI Thread::threadFunc(LPVOID _arg)
+ struct TlsDataInternal
{
- Thread* thread = (Thread*)_arg;
- int32_t result = thread->entry();
- return result;
+#if BX_PLATFORM_WINDOWS
+ uint32_t m_id;
+#elif !(BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT)
+ pthread_key_t m_id;
+#endif // BX_PLATFORM_*
+ };
+
+#if BX_PLATFORM_WINDOWS
+ TlsData::TlsData()
+ {
+ BX_STATIC_ASSERT(sizeof(TlsDataInternal) <= sizeof(m_internal) );
+
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ ti->m_id = TlsAlloc();
+ BX_CHECK(TLS_OUT_OF_INDEXES != ti->m_id, "Failed to allocated TLS index (err: 0x%08x).", GetLastError() );
}
-#else
- void* Thread::threadFunc(void* _arg)
+
+ TlsData::~TlsData()
{
- Thread* thread = (Thread*)_arg;
- union
- {
- void* ptr;
- int32_t i;
- } cast;
- cast.i = thread->entry();
- return cast.ptr;
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ BOOL result = TlsFree(ti->m_id);
+ BX_CHECK(0 != result, "Failed to free TLS index (err: 0x%08x).", GetLastError() ); BX_UNUSED(result);
}
-#endif // BX_PLATFORM_
+
+ void* TlsData::get() const
+ {
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ return TlsGetValue(ti->m_id);
+ }
+
+ void TlsData::set(void* _ptr)
+ {
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ TlsSetValue(ti->m_id, _ptr);
+ }
+
+#elif !(BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT)
+
+ TlsData::TlsData()
+ {
+ BX_STATIC_ASSERT(sizeof(TlsDataInternal) <= sizeof(m_internal) );
+
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ int result = pthread_key_create(&ti->m_id, NULL);
+ BX_CHECK(0 == result, "pthread_key_create failed %d.", result); BX_UNUSED(result);
+ }
+
+ TlsData::~TlsData()
+ {
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ int result = pthread_key_delete(ti->m_id);
+ BX_CHECK(0 == result, "pthread_key_delete failed %d.", result); BX_UNUSED(result);
+ }
+
+ void* TlsData::get() const
+ {
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ return pthread_getspecific(ti->m_id);
+ }
+
+ void TlsData::set(void* _ptr)
+ {
+ TlsDataInternal* ti = (TlsDataInternal*)m_internal;
+ int result = pthread_setspecific(ti->m_id, _ptr);
+ BX_CHECK(0 == result, "pthread_setspecific failed %d.", result); BX_UNUSED(result);
+ }
+#endif // BX_PLATFORM_*
} // namespace bx