UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
PThreadRunnableThread.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5// HEADER_UNIT_UNSUPPORTED - Unsupported platform
6
7#include "CoreTypes.h"
9#include "HAL/UnrealMemory.h"
11#include "Logging/LogMacros.h"
12#include "CoreGlobals.h"
13#include "HAL/Event.h"
14#include "HAL/Runnable.h"
15#include "HAL/RunnableThread.h"
16#include "HAL/PlatformProcess.h"
17#include "HAL/ThreadManager.h"
18
19#if PLATFORM_USE_PTHREADS
20
25class FRunnableThreadPThread : public FRunnableThread
26{
27
28protected:
29
34
39
40 typedef void *(*PthreadEntryPoint)(void *arg);
41
46 virtual int32 TranslateThreadPriority(EThreadPriority Priority)
47 {
48 // these are some default priorities
49 switch (Priority)
50 {
51 // 0 is the lowest, 31 is the highest possible priority for pthread
52 case TPri_Highest: case TPri_TimeCritical: return 30;
53 case TPri_AboveNormal: return 25;
54 case TPri_Normal: return 15;
55 case TPri_BelowNormal: return 5;
56 case TPri_Lowest: return 1;
57 case TPri_SlightlyBelowNormal: return 14;
58 case TPri_Num:
59 default:
60 UE_LOG(LogHAL, Fatal, TEXT("Unknown Priority passed to FRunnableThreadPThread::TranslateThreadPriority()"));
61 return 15;
62 }
63 }
64
66 {
67 struct sched_param Sched;
68 FMemory::Memzero(&Sched, sizeof(struct sched_param));
69 int32 Policy = SCHED_RR;
70
71 // Read the current policy
73
74 // set the priority appropriately
75 Sched.sched_priority = TranslateThreadPriority(NewPriority);
77 }
78
87 virtual int CreateThreadWithName(pthread_t* HandlePtr, pthread_attr_t* AttrPtr, PthreadEntryPoint Proc, void* Arg, const ANSICHAR* /*Name*/)
88 {
89 // by default, we ignore the name since it's not in the standard pthreads
90 return pthread_create(HandlePtr, AttrPtr, Proc, Arg);
91 }
92
96 virtual int GetDefaultStackSize()
97 {
98 // Some information on default stack sizes, selected when given 0:
99 // - On Windows, all threads get 1MB: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx
100 // - On Mac, main thread gets 8MB,
101 // - all other threads get 512 kB when created through pthread or NSThread, and only 4kB when through MPTask()
102 // ( http://developer.apple.com/library/mac/#qa/qa1419/_index.html )
103 return 0;
104 }
105
109 virtual uint32 AdjustStackSize(uint32 InStackSize)
110 {
111 // allow the platform to override default stack size
112 if (InStackSize == 0)
113 {
114 InStackSize = GetDefaultStackSize();
115 }
116 return InStackSize;
117 }
118
120 {
121 // allow platform to adjust stack size
122 InStackSize = AdjustStackSize(InStackSize);
123
124 if (InStackSize != 0)
125 {
127 {
128 // we'll use this the attribute if this succeeds, otherwise, we'll wing it without it.
129 const size_t StackSize = (size_t)InStackSize;
130 if (pthread_attr_setstacksize(ThreadAttr, StackSize) != 0)
131 {
132 UE_LOG(LogHAL, Log, TEXT("Failed to change pthread stack size to %d bytes"), (int)InStackSize);
133 }
134 return true;
135 }
136 else
137 {
138 UE_LOG(LogHAL, Log, TEXT("Failed to init thread attr"));
139 }
140 }
141
142 return false;
143 }
144
146 {
147 *OutThreadCreated = false;
150
151 const int ThreadErrno = CreateThreadWithName(HandlePtr, ThreadAttrPtr, Proc, Arg, TCHAR_TO_ANSI(*ThreadName));
153 if (ThreadAttrPtr)
154 {
156 }
157
158 // Move the thread to the specified processors if requested
159 if (!*OutThreadCreated)
160 {
161 UE_LOG(LogHAL, Log, TEXT("Failed to create thread! (err=%d, %s)"), ThreadErrno, UTF8_TO_TCHAR(strerror(ThreadErrno)));
162 }
163
164 return *OutThreadCreated;
165 }
166
171 static void *STDCALL _ThreadProc(void *pThis)
172 {
173 check(pThis);
174
175 FRunnableThreadPThread* ThisThread = (FRunnableThreadPThread*)pThis;
176
177 // cache the thread ID for this thread (defined by the platform)
179
181
182 // set the affinity. This function sets affinity on the current thread, so don't call in the Create function which will trash the main thread affinity.
184
185 // run the thread!
186 ThisThread->PreRun();
187 ThisThread->Run();
188 ThisThread->PostRun();
189
191 return NULL;
192 }
193
195 {
196 return _ThreadProc;
197 }
198
202 virtual void PreRun()
203 {
204 }
205
209 virtual void PostRun()
210 {
211 }
212
217 uint32 Run();
218
229 {
230 // Clean up our thread if it is still active
232 {
233 Kill(true);
234 }
235 checkf(!bThreadStartedAndNotCleanedUp, TEXT("Thread still not cleaned up after Kill(true)!"));
236 ThreadID = 0;
237 }
238
239public:
240 FRunnableThreadPThread()
242 {
243 }
244
246 {
248 }
249
250 virtual void SetThreadPriority(EThreadPriority NewPriority) override
251 {
252 // Don't bother calling the OS if there is no need
253 if (NewPriority != ThreadPriority)
254 {
255 ThreadPriority = NewPriority;
257 }
258 }
259
260 virtual void Suspend(bool bShouldPause = 1) override
261 {
262 check(Thread);
263 // Impossible in pthreads!
264 }
265
266 virtual bool Kill(bool bShouldWait) override
267 {
268 check(Thread && "Did you forget to call Create()?");
269 bool bDidExitOK = true;
270 // Let the runnable have a chance to stop without brute force killing
271 if (Runnable)
272 {
273 Runnable->Stop();
274 }
275 // If waiting was specified, wait the amount of time. If that fails,
276 // brute force kill that thread. Very bad as that might leak.
278 {
279 int JoinResult = pthread_join(Thread, nullptr);
280
281 UE_CLOG(JoinResult != 0, LogHAL, Warning, TEXT("Failed to join thread %u (%s). (err=%d, %s)"), ThreadID, *ThreadName, JoinResult, UTF8_TO_TCHAR(strerror(JoinResult)));
282
283 bDidExitOK = (JoinResult == 0);
285 }
286
287 // It's not really safe to kill a pthread. So don't do it.
288 return bDidExitOK;
289 }
290
291 virtual void WaitForCompletion() override
292 {
293 // Block until this thread exits
295 {
296 int JoinResult = pthread_join(Thread, nullptr);
297
298 UE_CLOG(JoinResult != 0, LogHAL, Warning, TEXT("Failed to join thread %u (%s). (err=%d, %s)"), ThreadID, *ThreadName, JoinResult, UTF8_TO_TCHAR(strerror(JoinResult)));
299
301 }
302 }
303
304protected:
305
306 virtual bool CreateInternal(FRunnable* InRunnable, const TCHAR* InThreadName,
310 {
312 Runnable = InRunnable;
313
314 // Create a sync event to guarantee the Init() function is called first
315 ThreadInitSyncEvent = FPlatformProcess::GetSynchEventFromPool(true);
316 // A name for the thread in for debug purposes. _ThreadProc will set it.
317 ThreadName = InThreadName ? InThreadName : TEXT("Unnamed UE4");
318 ThreadPriority = InThreadPri; // Make sure the thread priority is correct during init
319 ThreadAffinityMask = InThreadAffinityMask;
320
321 // Create the new thread
323 // If it fails, clear all the vars
324 if (ThreadCreated)
325 {
326 // Let the thread start up, then set the name for debug purposes.
327 ThreadInitSyncEvent->Wait((uint32)-1); // infinite wait
328
329 // set the priority
330 ThreadPriority = TPri_Num; // set to Num (invalid) to ensure that the priority will be set below
332 }
333 else // If it fails, clear all the vars
334 {
335 Runnable = NULL;
336 }
337
338 // Cleanup the sync event
339 FPlatformProcess::ReturnSynchEventToPool( ThreadInitSyncEvent );
340 ThreadInitSyncEvent = nullptr;
342 }
343};
344
345#endif
#define NULL
Definition oodle2base.h:134
#define STDCALL
Definition AndroidPlatform.h:136
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#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::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::ANSICHAR ANSICHAR
An ANSI character. Normally a signed type.
Definition Platform.h:1131
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
s expects dereferenced FString s expects ANSICHAR *or UTF8CHAR s expects ANSICHAR *or UTF8CHAR *but got TCHAR *use ls S expects dereferenced FAnsiString or FUtf8String S expects character pointer but got S expects ANSICHAR *or UTF8CHAR S expects ANSICHAR *or UTF8CHAR *but got TCHAR *use s hs expects dereferenced FAnsiString or FUtf8String hs expects ANSICHAR *or UTF8CHAR hs expects ANSICHAR *or UTF8CHAR *but got TCHAR *use s ls expects character pointer but got ls expects TCHAR ls expects TCHAR *but got ANSICHAR *or UTF8CHAR *use hs c expects ANSICHAR or UTF8CHAR p expects a pointer unsupported format not enough arguments provided to format string d expects integral arg(eg. `char`, `int`, `long`, etc.)") X(ZNeedsIntegerArg
EThreadPriority
Definition GenericPlatformAffinity.h:26
@ TPri_TimeCritical
Definition GenericPlatformAffinity.h:33
@ TPri_AboveNormal
Definition GenericPlatformAffinity.h:28
@ TPri_Lowest
Definition GenericPlatformAffinity.h:31
@ TPri_SlightlyBelowNormal
Definition GenericPlatformAffinity.h:32
@ TPri_Highest
Definition GenericPlatformAffinity.h:30
@ TPri_BelowNormal
Definition GenericPlatformAffinity.h:29
@ TPri_Num
Definition GenericPlatformAffinity.h:34
@ TPri_Normal
Definition GenericPlatformAffinity.h:27
EThreadCreateFlags
Definition GenericPlatformAffinity.h:38
#define UE_CLOG(Condition, CategoryName, Verbosity, Format,...)
Definition LogMacros.h:298
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
#define UTF8_TO_TCHAR(str)
Definition StringConv.h:1022
#define TCHAR_TO_ANSI(str)
Definition StringConv.h:1019
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition RunnableThread.h:20
virtual void SetThreadPriority(EThreadPriority NewPriority)=0
Definition Runnable.h:20
CORE_API void AddThread(uint32 ThreadId, FRunnableThread *Thread)
Definition ThreadingBase.cpp:489
static CORE_API FThreadManager & Get()
Definition ThreadingBase.cpp:685
Type SetThreadPriority(Type ThreadAndIndex, Type ThreadPriority)
Definition TaskGraphInterfaces.h:190
@ Kill
Definition ParticleModuleCollisionGPU.h:28
void Suspend(bool bIsInterrupt=false)
Definition LaunchIOS.cpp:60
void Run(FMassRuntimePipeline &RuntimePipeline, FProcessingContext &ProcessingContext)
Definition MassExecutor.cpp:25
@ false
Definition radaudio_common.h:23
static CORE_API void SetThreadAffinityMask(uint64 AffinityMask)
Definition AndroidPlatformProcess.cpp:76
static uint32 GetCurrentThreadId(void)
Definition AndroidPlatformTLS.h:20
static CORE_API class FEvent * GetSynchEventFromPool(bool bIsManualReset=false)
Definition GenericPlatformProcess.cpp:576
static CORE_API void ReturnSynchEventToPool(FEvent *Event)
Definition GenericPlatformProcess.cpp:589
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131