Core: Add thread extension functions
This commit is contained in:
parent
628a3a8375
commit
bf0d7674c7
|
|
@ -0,0 +1,25 @@
|
|||
// 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_THREADEXT_HPP
|
||||
#define NAZARA_CORE_THREADEXT_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <thread>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
NAZARA_CORE_API std::string GetCurrentThreadName();
|
||||
NAZARA_CORE_API std::string GetThreadName(std::thread& thread);
|
||||
|
||||
NAZARA_CORE_API void SetCurrentThreadName(const char* name);
|
||||
NAZARA_CORE_API void SetThreadName(std::thread& thread, const char* name);
|
||||
}
|
||||
|
||||
#include <Nazara/Core/ThreadExt.inl>
|
||||
|
||||
#endif // NAZARA_CORE_THREADEXT_HPP
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// 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/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include <Nazara/Audio/AudioDevice.hpp>
|
||||
#include <Nazara/Audio/AudioSource.hpp>
|
||||
#include <Nazara/Audio/SoundStream.hpp>
|
||||
#include <Nazara/Core/ThreadExt.hpp>
|
||||
#include <NazaraUtils/CallOnExit.hpp>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
|
|
@ -425,6 +426,8 @@ namespace Nz
|
|||
|
||||
void Music::MusicThread(std::condition_variable& cv, std::mutex& m, std::exception_ptr& err, bool startPaused)
|
||||
{
|
||||
SetCurrentThreadName("MusicThread");
|
||||
|
||||
std::optional<std::lock_guard<std::recursive_mutex>> exitLock;
|
||||
|
||||
// Allocation of streaming buffers
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// 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/Posix/ThreadImpl.hpp>
|
||||
#include <array>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
// https://stackoverflow.com/questions/2369738/how-to-set-the-name-of-a-thread-in-linux-pthreads
|
||||
|
||||
namespace Nz::PlatformImpl
|
||||
{
|
||||
pthread_t GetCurrentThreadHandle()
|
||||
{
|
||||
return ::pthread_self();
|
||||
}
|
||||
|
||||
std::string GetThreadName(pthread_t threadHandle)
|
||||
{
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
std::array<char, 16> name;
|
||||
::pthread_getname_np(threadHandle, &name[0], name.size());
|
||||
|
||||
return std::string(&name[0]);
|
||||
#else
|
||||
return "<unsupported>";
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* threadName)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
::pthread_setname_np(::pthread_self(), threadName);
|
||||
#elif defined(__APPLE__)
|
||||
::pthread_setname_np(threadName);
|
||||
#elif defined(__FreeBSD__)
|
||||
::pthread_set_name_np(::pthread_self(), threadName);
|
||||
#else
|
||||
NazaraWarning("setting current thread name is not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetThreadName(pthread_t threadHandle, const char* threadName)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
::pthread_setname_np(threadHandle, threadName);
|
||||
#elif defined(__APPLE__)
|
||||
NazaraWarning("only current thread name can be set on MacOS X");
|
||||
#elif defined(__FreeBSD__)
|
||||
::pthread_set_name_np(threadHandle, threadName);
|
||||
#else
|
||||
NazaraWarning("setting a thread name is not supported on this platform");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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_POSIX_THREADIMPL_HPP
|
||||
#define NAZARA_CORE_POSIX_THREADIMPL_HPP
|
||||
|
||||
#include <NazaraUtils/Prerequisites.hpp>
|
||||
#include <string>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace Nz::PlatformImpl
|
||||
{
|
||||
using ThreadHandle = pthread_t;
|
||||
|
||||
pthread_t GetCurrentThreadHandle();
|
||||
std::string GetCurrentThreadName();
|
||||
std::string GetThreadName(pthread_t threadHandle);
|
||||
void SetCurrentThreadName(const char* threadName);
|
||||
void SetThreadName(pthread_t threadHandle, const char* threadName);
|
||||
}
|
||||
|
||||
#endif // NAZARA_CORE_POSIX_THREADIMPL_HPP
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// 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/ThreadExt.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Core/Win32/ThreadImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
#include <Nazara/Core/Posix/ThreadImpl.hpp>
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
std::string GetCurrentThreadName()
|
||||
{
|
||||
return PlatformImpl::GetCurrentThreadName();
|
||||
}
|
||||
|
||||
std::string GetThreadName(std::thread& thread)
|
||||
{
|
||||
// std::thread::native_handle returns a void* with MSVC instead of a HANDLE
|
||||
return PlatformImpl::GetThreadName(static_cast<PlatformImpl::ThreadHandle>(thread.native_handle()));
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* name)
|
||||
{
|
||||
PlatformImpl::SetCurrentThreadName(name);
|
||||
}
|
||||
|
||||
void SetThreadName(std::thread& thread, const char* name)
|
||||
{
|
||||
// std::thread::native_handle returns a void* with MSVC instead of a HANDLE
|
||||
PlatformImpl::SetThreadName(static_cast<PlatformImpl::ThreadHandle>(thread.native_handle()), name);
|
||||
}
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue