Disable dynamic buckets in ThreadLocal on non-Desktop platforms that use fixed set of thread count

This commit is contained in:
Wojtek Figat
2024-02-08 10:47:55 +01:00
parent 082768d08c
commit f9ca69d8a9

View File

@@ -5,6 +5,8 @@
#include "Engine/Core/Types/BaseTypes.h" #include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Platform/Platform.h" #include "Engine/Platform/Platform.h"
#define THREAD_LOCAL_USE_DYNAMIC_BUCKETS (PLATFORM_DESKTOP)
/// <summary> /// <summary>
/// Per-thread local variable storage for basic types (POD). Implemented using atomic with per-thread storage indexed via thread id hashing. Consider using 'THREADLOCAL' define before the variable instead. /// Per-thread local variable storage for basic types (POD). Implemented using atomic with per-thread storage indexed via thread id hashing. Consider using 'THREADLOCAL' define before the variable instead.
/// </summary> /// </summary>
@@ -12,7 +14,6 @@ template<typename T, int32 MaxThreads = PLATFORM_THREADS_LIMIT>
class ThreadLocal class ThreadLocal
{ {
protected: protected:
constexpr static int32 DynamicMaxThreads = 1024;
static_assert(TIsPODType<T>::Value, "Only POD types are supported"); static_assert(TIsPODType<T>::Value, "Only POD types are supported");
struct Bucket struct Bucket
@@ -22,7 +23,10 @@ protected:
}; };
Bucket _staticBuckets[MaxThreads]; Bucket _staticBuckets[MaxThreads];
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
Bucket* _dynamicBuckets = nullptr; Bucket* _dynamicBuckets = nullptr;
constexpr static int32 DynamicMaxThreads = 1024;
#endif
public: public:
ThreadLocal() ThreadLocal()
@@ -30,10 +34,12 @@ public:
Platform::MemoryClear(_staticBuckets, sizeof(_staticBuckets)); Platform::MemoryClear(_staticBuckets, sizeof(_staticBuckets));
} }
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
~ThreadLocal() ~ThreadLocal()
{ {
Platform::Free(_dynamicBuckets); Platform::Free(_dynamicBuckets);
} }
#endif
public: public:
FORCE_INLINE T& Get() FORCE_INLINE T& Get()
@@ -54,6 +60,7 @@ public:
if (Platform::AtomicRead((int64 volatile*)&_staticBuckets[i].ThreadID) != 0) if (Platform::AtomicRead((int64 volatile*)&_staticBuckets[i].ThreadID) != 0)
result++; result++;
} }
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets)) if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets))
{ {
for (int32 i = 0; i < MaxThreads; i++) for (int32 i = 0; i < MaxThreads; i++)
@@ -62,6 +69,7 @@ public:
result++; result++;
} }
} }
#endif
return result; return result;
} }
@@ -73,6 +81,7 @@ public:
if (Platform::AtomicRead((int64 volatile*)&_staticBuckets[i].ThreadID) != 0) if (Platform::AtomicRead((int64 volatile*)&_staticBuckets[i].ThreadID) != 0)
result.Add(_staticBuckets[i].Value); result.Add(_staticBuckets[i].Value);
} }
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets)) if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets))
{ {
for (int32 i = 0; i < MaxThreads; i++) for (int32 i = 0; i < MaxThreads; i++)
@@ -81,13 +90,16 @@ public:
result.Add(dynamicBuckets[i].Value); result.Add(dynamicBuckets[i].Value);
} }
} }
#endif
} }
void Clear() void Clear()
{ {
Platform::MemoryClear(_staticBuckets, sizeof(_staticBuckets)); Platform::MemoryClear(_staticBuckets, sizeof(_staticBuckets));
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
Platform::Free(_dynamicBuckets); Platform::Free(_dynamicBuckets);
_dynamicBuckets = nullptr; _dynamicBuckets = nullptr;
#endif
} }
protected: protected:
@@ -109,6 +121,7 @@ protected:
spaceLeft--; spaceLeft--;
} }
#if THREAD_LOCAL_USE_DYNAMIC_BUCKETS
// Allocate dynamic buckets if missing // Allocate dynamic buckets if missing
DYNAMIC: DYNAMIC:
auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets); auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets);
@@ -136,6 +149,8 @@ protected:
index = (index + 1) & (DynamicMaxThreads - 1); index = (index + 1) & (DynamicMaxThreads - 1);
spaceLeft--; spaceLeft--;
} }
#endif
return *(Bucket*)nullptr; return *(Bucket*)nullptr;
} }
}; };