UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MicrosoftRunnableThread.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
6#include "CoreGlobals.h"
7#include "CoreTypes.h"
8#include "HAL/Event.h"
10#include "HAL/PlatformProcess.h"
11#include "HAL/Runnable.h"
12#include "HAL/RunnableThread.h"
13#include "HAL/ThreadManager.h"
16
17class FRunnable;
18
24 : public FRunnableThread
25{
27 HANDLE Thread = 0;
28
33 static ::DWORD STDCALL _ThreadProc(LPVOID pThis)
34 {
35 check(pThis);
38 return ThisThread->GuardedRun();
39 }
40
42 uint32 GuardedRun();
43
48 uint32 Run();
49
50public:
52 {
53 if (Thread)
54 {
55 Kill(true);
56 }
57 }
58
65
66 virtual void Suspend(bool bShouldPause = true) override
67 {
69 if (bShouldPause == true)
70 {
72 }
73 else
74 {
76 }
77 }
78
79 virtual bool Kill(bool bShouldWait) override
80 {
81 check(Thread && "Did you forget to call Create()?");
82 bool bDidExitOK = true;
83
84 // Let the runnable have a chance to stop without brute force killing
85 if (Runnable)
86 {
87 Runnable->Stop();
88 }
89
90 if (bShouldWait == true)
91 {
92 // Wait indefinitely for the thread to finish. IMPORTANT: It's not safe to just go and
93 // kill the thread with TerminateThread() as it could have a mutex lock that's shared
94 // with a thread that's continuing to run, which would cause that other thread to
95 // dead-lock.
96 //
97 // This can manifest itself in code as simple as the synchronization
98 // object that is used by our logging output classes
99
101 }
102
104 Thread = NULL;
105
106#if UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
107 const uint64 FakeAddress = uint64(this) | (1ull << 47);
109 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, (const void*)FakeAddress));
110 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Platform, (const void*)FakeAddress));
111#endif // UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
112
113 return bDidExitOK;
114 }
115
116 virtual void WaitForCompletion() override
117 {
119 }
120
121 virtual bool SetThreadAffinity(const FThreadAffinity& Affinity) override;
122
124protected:
125
130 {
134
135 // Create a sync event to guarantee the Init() function is called first
137
138 ThreadName = InThreadName ? InThreadName : TEXT("Unnamed UE");
140
141 // Create the new thread
142 {
143#if UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
144 LLM_SCOPE(ELLMTag::ThreadStack);
145 LLM_PLATFORM_SCOPE(ELLMTag::ThreadStackPlatform);
146 const uint64 FakeAddress = uint64(this) | (1ull << 47);
147 constexpr uint64 DefaultStackSize = 1024 * 1024; // 1 MiB, unless overridden in the .def file
148 constexpr uint32 DefaultAlignment = 64 * 1024; // 64 KiB, typical system's allocation granularity
149 // Size of zero indicates using default thread stack size.
154 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, (const void*)FakeAddress, ActualStackSize));
155 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Platform, (const void*)FakeAddress, ActualStackSize));
156#endif // UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
157
158 // Create the thread as suspended, so we can ensure ThreadId is initialized and the thread manager knows about the thread before it runs.
159 Thread = CreateThread(NULL, InStackSize, _ThreadProc, this, STACK_SIZE_PARAM_IS_A_RESERVATION | CREATE_SUSPENDED, (::DWORD*)&ThreadID);
160 }
161
162 // If it fails, clear all the vars
163 if (Thread == NULL)
164 {
165#if UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
166 const uint64 FakeAddress = uint64(this) | (1ull << 47);
168 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, (const void*)FakeAddress));
169 LLM_IF_ENABLED(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Platform, (const void*)FakeAddress));
170#endif // UE_MEMORY_TRACE_ENABLED || ENABLE_LOW_LEVEL_MEM_TRACKER
171
172 Runnable = nullptr;
173 }
174 else
175 {
176 // Set the priority before resuming the thread, since the thread itself could end up manipulating its own priority
177 // and cause a race condition.
178 ThreadPriority = TPri_Normal; // Set back to default in case any SetThreadPrio() impls compare against current value to reduce syscalls
180
182
183 // Let the thread start up
185 }
186
187 // Cleanup the sync event
189 ThreadInitSyncEvent = nullptr;
190 return Thread != NULL;
191 }
192};
#define NULL
Definition oodle2base.h:134
#define STDCALL
Definition AndroidPlatform.h:136
#define check(expr)
Definition AssertionMacros.h:314
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
EThreadPriority
Definition GenericPlatformAffinity.h:26
@ TPri_Normal
Definition GenericPlatformAffinity.h:27
EThreadCreateFlags
Definition GenericPlatformAffinity.h:38
#define LLM_IF_ENABLED(...)
Definition LowLevelMemTracker.h:1093
#define LLM_PLATFORM_SCOPE(...)
Definition LowLevelMemTracker.h:1101
#define LLM_SCOPE(...)
Definition LowLevelMemTracker.h:1095
void MemoryTrace_MarkAllocAsHeap(uint64 Address, HeapId Heap)
Definition MemoryTrace.h:197
void MemoryTrace_Free(uint64 Address, HeapId RootHeap=EMemoryTraceRootHeap::SystemMemory, uint32 ExternalCallstackId=0)
Definition MemoryTrace.h:200
@ SystemMemory
Definition MemoryTrace.h:35
void MemoryTrace_Alloc(uint64 Address, uint64 Size, uint32 Alignment, HeapId RootHeap=EMemoryTraceRootHeap::SystemMemory, uint32 ExternalCallstackId=0)
Definition MemoryTrace.h:199
uint32_t uint32
Definition binka_ue_file_header.h:6
virtual bool Wait(uint32 WaitTime, const bool bIgnoreThreadIdleStats=false)=0
Definition MicrosoftRunnableThread.h:25
virtual bool Kill(bool bShouldWait) override
Definition MicrosoftRunnableThread.h:79
~FRunnableThreadWin()
Definition MicrosoftRunnableThread.h:51
virtual bool CreateInternal(FRunnable *InRunnable, const TCHAR *InThreadName, uint32 InStackSize=0, EThreadPriority InThreadPri=TPri_Normal, uint64 InThreadAffinityMask=0, EThreadCreateFlags InCreateFlags=EThreadCreateFlags::None) override
Definition MicrosoftRunnableThread.h:126
virtual void SetThreadPriority(EThreadPriority NewPriority) override
Definition MicrosoftRunnableThread.h:59
virtual void WaitForCompletion() override
Definition MicrosoftRunnableThread.h:116
virtual bool SetThreadAffinity(const FThreadAffinity &Affinity) override
Definition WindowsRunnableThread.cpp:114
static int TranslateThreadPriority(EThreadPriority Priority)
Definition WindowsRunnableThread.cpp:12
virtual void Suspend(bool bShouldPause=true) override
Definition MicrosoftRunnableThread.h:66
Definition RunnableThread.h:20
EThreadPriority ThreadPriority
Definition RunnableThread.h:186
FEvent * ThreadInitSyncEvent
Definition RunnableThread.h:180
FString ThreadName
Definition RunnableThread.h:174
FRunnable * Runnable
Definition RunnableThread.h:177
uint64 ThreadAffinityMask
Definition RunnableThread.h:183
uint32 ThreadID
Definition RunnableThread.h:189
Definition Runnable.h:20
virtual void Stop()
Definition Runnable.h:53
CORE_API void AddThread(uint32 ThreadId, FRunnableThread *Thread)
Definition ThreadingBase.cpp:489
static CORE_API FThreadManager & Get()
Definition ThreadingBase.cpp:685
static CORE_API class FEvent * GetSynchEventFromPool(bool bIsManualReset=false)
Definition GenericPlatformProcess.cpp:576
static CORE_API void ReturnSynchEventToPool(FEvent *Event)
Definition GenericPlatformProcess.cpp:589
Definition PlatformAffinity.h:10