Core: Add thread extension functions

This commit is contained in:
SirLynix
2023-06-07 13:35:40 +02:00
parent 628a3a8375
commit bf0d7674c7
8 changed files with 288 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Win32/ThreadImpl.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <NazaraUtils/CallOnExit.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz::PlatformImpl
{
namespace NAZARA_ANONYMOUS_NAMESPACE
{
// Windows 10, version 1607 added SetThreadDescription in order to name a thread
using SetThreadDescriptionFunc = HRESULT(WINAPI*)(HANDLE hThread, PCWSTR lpThreadDescription);
#ifdef NAZARA_COMPILER_MSVC
#pragma pack(push,8)
struct THREADNAME_INFO
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
#pragma pack(pop)
#endif
}
HANDLE GetCurrentThreadHandle()
{
return ::GetCurrentThread();
}
std::string GetCurrentThreadName()
{
return GetThreadName(::GetCurrentThread());
}
std::string GetThreadName(HANDLE threadHandle)
{
PWSTR namePtr;
HRESULT hr = ::GetThreadDescription(threadHandle, &namePtr);
if (FAILED(hr))
return "<GetThreadDescription failed: " + std::to_string(HRESULT_CODE(hr)) + ">";
CallOnExit freeName([&] { LocalFree(namePtr); });
return FromWideString(namePtr);
}
void RaiseThreadNameException(DWORD threadId, const char* threadName)
{
#ifdef NAZARA_COMPILER_MSVC
NAZARA_USE_ANONYMOUS_NAMESPACE
if (!::IsDebuggerPresent())
return;
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = threadId;
info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
#pragma warning(pop)
#else
NazaraWarning("ThreadName exception is only supported with MSVC");
#endif
}
void SetCurrentThreadName(const char* threadName)
{
SetThreadName(::GetCurrentThread(), threadName);
}
void SetThreadName(HANDLE threadHandle, const char* threadName)
{
NAZARA_USE_ANONYMOUS_NAMESPACE
// Try to use SetThreadDescription if available
static SetThreadDescriptionFunc SetThreadDescription = reinterpret_cast<SetThreadDescriptionFunc>(::GetProcAddress(::GetModuleHandleW(L"Kernel32.dll"), "SetThreadDescription"));
if (SetThreadDescription)
SetThreadDescription(threadHandle, ToWideString(threadName).data());
else
RaiseThreadNameException(::GetThreadId(threadHandle), threadName);
}
}
#include <Nazara/Core/AntiWindows.hpp>

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_CORE_WIN32_THREADIMPL_HPP
#define NAZARA_CORE_WIN32_THREADIMPL_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <string>
#include <Windows.h>
namespace Nz::PlatformImpl
{
using ThreadHandle = HANDLE;
HANDLE GetCurrentThreadHandle();
std::string GetCurrentThreadName();
std::string GetThreadName(HANDLE threadHandle);
void RaiseThreadNameException(DWORD threadId, const char* threadName);
void SetCurrentThreadName(const char* threadName);
void SetThreadName(HANDLE threadHandle, const char* threadName);
}
#endif // NAZARA_CORE_WIN32_THREADIMPL_HPP