aboutsummaryrefslogtreecommitdiff
path: root/zencore/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zencore/thread.cpp')
-rw-r--r--zencore/thread.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/zencore/thread.cpp b/zencore/thread.cpp
index 20ab19f56..6f27ee528 100644
--- a/zencore/thread.cpp
+++ b/zencore/thread.cpp
@@ -14,6 +14,61 @@
namespace zen {
+#if ZEN_PLATFORM_WINDOWS
+// The information on how to set the thread name comes from
+// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
+const DWORD kVCThreadNameException = 0x406D1388;
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+// The SetThreadDescription API was brought in version 1607 of Windows 10.
+typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
+// This function has try handling, so it is separated out of its caller.
+void
+SetNameInternal(DWORD thread_id, const char* name)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = name;
+ info.dwThreadID = thread_id;
+ info.dwFlags = 0;
+ __try
+ {
+ RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(DWORD), reinterpret_cast<DWORD_PTR*>(&info));
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+#endif
+
+void
+SetCurrentThreadName([[maybe_unused]] std::string_view ThreadName)
+{
+#if ZEN_PLATFORM_WINDOWS
+ // The SetThreadDescription API works even if no debugger is attached.
+ static auto SetThreadDescriptionFunc =
+ reinterpret_cast<SetThreadDescription>(::GetProcAddress(::GetModuleHandle(L"Kernel32.dll"), "SetThreadDescription"));
+
+ if (SetThreadDescriptionFunc)
+ {
+ SetThreadDescriptionFunc(::GetCurrentThread(), Utf8ToWide(ThreadName).c_str());
+ }
+ // The debugger needs to be around to catch the name in the exception. If
+ // there isn't a debugger, we are just needlessly throwing an exception.
+ if (!::IsDebuggerPresent())
+ return;
+
+ std::string ThreadNameZ{ThreadName};
+ SetNameInternal(GetCurrentThreadId(), ThreadNameZ.c_str());
+#else
+#endif
+} // namespace zen
+
void
RwLock::AcquireShared()
{