You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #jira #ROBOMERGE-SOURCE: CL 5307320 in //UE4/Release-4.22/... #ROBOMERGE-BOT: RELEASE (Release-4.22 -> Main) [CL 5314647 by ben marsh in Main branch]
187 lines
3.4 KiB
C++
187 lines
3.4 KiB
C++
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
|
|
|
#include "LC_Thread.h"
|
|
#include "LC_Platform.h"
|
|
#include "LC_Logging.h"
|
|
#include <process.h>
|
|
|
|
// BEGIN EPIC MODS
|
|
#pragma warning(push)
|
|
#pragma warning(disable:6322) // warning C6322: Empty _except block.
|
|
#pragma warning(disable:6258) // warning C6258: Using TerminateThread does not allow proper thread clean up.
|
|
// END EPIC MODS
|
|
|
|
namespace
|
|
{
|
|
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
|
|
|
struct THREADNAME_INFO
|
|
{
|
|
ULONG_PTR dwType; // Must be 0x1000.
|
|
ULONG_PTR szName; // Pointer to name (in user addr space).
|
|
ULONG_PTR dwThreadID; // Thread ID (-1 = caller thread).
|
|
ULONG_PTR dwFlags; // Reserved for future use, must be zero.
|
|
};
|
|
|
|
|
|
static void SetThreadName(const char* threadName)
|
|
{
|
|
// code for setting a thread's name taken from http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
|
// note that the pragma directives in the code sample are wrong, and will not work for 32-bit builds.
|
|
THREADNAME_INFO info;
|
|
info.dwType = 0x1000;
|
|
info.szName = reinterpret_cast<ULONG_PTR>(threadName);
|
|
info.dwThreadID = static_cast<ULONG_PTR>(-1);
|
|
info.dwFlags = 0;
|
|
|
|
__try
|
|
{
|
|
RaiseException(MS_VC_EXCEPTION, 0, 4u, reinterpret_cast<ULONG_PTR*>(&info));
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
namespace thread
|
|
{
|
|
unsigned int GetId(void)
|
|
{
|
|
return ::GetCurrentThreadId();
|
|
}
|
|
|
|
|
|
unsigned int GetId(Handle handle)
|
|
{
|
|
return ::GetThreadId(handle);
|
|
}
|
|
|
|
|
|
Handle Create(unsigned int stackSize, Function function, void* context)
|
|
{
|
|
const uintptr_t result = _beginthreadex(nullptr, stackSize, function, context, 0u, nullptr);
|
|
if (result == 0u)
|
|
{
|
|
const DWORD error = ::GetLastError();
|
|
LC_ERROR_USER("Error 0x%X while trying to create thread", error);
|
|
}
|
|
|
|
return reinterpret_cast<Handle>(result);
|
|
}
|
|
|
|
|
|
void Join(Handle handle)
|
|
{
|
|
::WaitForSingleObject(handle, INFINITE);
|
|
}
|
|
|
|
|
|
void Terminate(Handle handle)
|
|
{
|
|
::TerminateThread(handle, 0u);
|
|
}
|
|
|
|
|
|
void Yield(void)
|
|
{
|
|
::_mm_pause();
|
|
}
|
|
|
|
|
|
void Sleep(unsigned int milliSeconds)
|
|
{
|
|
::Sleep(milliSeconds);
|
|
}
|
|
|
|
|
|
void CancelIO(Handle handle)
|
|
{
|
|
::CancelSynchronousIo(handle);
|
|
}
|
|
|
|
|
|
Handle Open(unsigned int threadId)
|
|
{
|
|
return ::OpenThread(THREAD_ALL_ACCESS, Windows::FALSE, threadId);
|
|
}
|
|
|
|
|
|
void Close(Handle& handle)
|
|
{
|
|
::CloseHandle(handle);
|
|
handle = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
|
|
void Suspend(Handle handle)
|
|
{
|
|
::SuspendThread(handle);
|
|
}
|
|
|
|
|
|
void Resume(Handle handle)
|
|
{
|
|
::ResumeThread(handle);
|
|
}
|
|
|
|
|
|
int GetPriority(Handle handle)
|
|
{
|
|
return ::GetThreadPriority(handle);
|
|
}
|
|
|
|
|
|
void SetPriority(Handle handle, int priority)
|
|
{
|
|
::SetThreadPriority(handle, priority);
|
|
}
|
|
|
|
|
|
Context GetContext(Handle handle)
|
|
{
|
|
CONTEXT threadContext = {};
|
|
threadContext.ContextFlags = CONTEXT_ALL;
|
|
::GetThreadContext(handle, &threadContext);
|
|
|
|
return threadContext;
|
|
}
|
|
|
|
|
|
void SetContext(Handle handle, const Context& context)
|
|
{
|
|
::SetThreadContext(handle, &context);
|
|
}
|
|
|
|
|
|
const void* ReadInstructionPointer(const Context& context)
|
|
{
|
|
#if LC_64_BIT
|
|
return reinterpret_cast<const void*>(context.Rip);
|
|
#else
|
|
return reinterpret_cast<const void*>(context.Eip);
|
|
#endif
|
|
}
|
|
|
|
|
|
void WriteInstructionPointer(Context& context, const void* ip)
|
|
{
|
|
#if LC_64_BIT
|
|
context.Rip = reinterpret_cast<DWORD64>(ip);
|
|
#else
|
|
context.Eip = reinterpret_cast<DWORD>(ip);
|
|
#endif
|
|
}
|
|
|
|
|
|
void SetName(const char* name)
|
|
{
|
|
SetThreadName(name);
|
|
}
|
|
}
|
|
|
|
// BEGIN EPIC MODS
|
|
#pragma warning(pop)
|
|
// END EPIC MODS
|