diff --git a/Source/Engine/Threading/JobSystem.cpp b/Source/Engine/Threading/JobSystem.cpp index 3cc9acc62..7f65e5210 100644 --- a/Source/Engine/Threading/JobSystem.cpp +++ b/Source/Engine/Threading/JobSystem.cpp @@ -75,7 +75,7 @@ public: namespace { JobSystemService JobSystemInstance; - Thread* Threads[PLATFORM_THREADS_LIMIT / 2] = {}; + Thread* Threads[(PLATFORM_THREADS_LIMIT + 1) / 2] = {}; int32 ThreadsCount = 0; bool JobStartingOnDispatch = true; volatile int64 ExitFlag = 0; diff --git a/Source/Engine/Threading/ThreadLocal.h b/Source/Engine/Threading/ThreadLocal.h index 049a62658..728662b00 100644 --- a/Source/Engine/Threading/ThreadLocal.h +++ b/Source/Engine/Threading/ThreadLocal.h @@ -7,10 +7,12 @@ #define THREAD_LOCAL_USE_DYNAMIC_BUCKETS (PLATFORM_DESKTOP) +#if PLATFORM_THREADS_LIMIT > 1 + /// /// 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. /// -template +template= 16 ? PLATFORM_THREADS_LIMIT : 16)> class ThreadLocal { protected: @@ -63,7 +65,7 @@ public: #if THREAD_LOCAL_USE_DYNAMIC_BUCKETS if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets)) { - for (int32 i = 0; i < MaxThreads; i++) + for (int32 i = 0; i < DynamicMaxThreads; i++) { if (Platform::AtomicRead((int64 volatile*)&dynamicBuckets[i].ThreadID) != 0) result++; @@ -84,7 +86,7 @@ public: #if THREAD_LOCAL_USE_DYNAMIC_BUCKETS if (auto dynamicBuckets = (Bucket*)Platform::AtomicRead((intptr volatile*)&_dynamicBuckets)) { - for (int32 i = 0; i < MaxThreads; i++) + for (int32 i = 0; i < DynamicMaxThreads; i++) { if (Platform::AtomicRead((int64 volatile*)&dynamicBuckets[i].ThreadID) != 0) result.Add(dynamicBuckets[i].Value); @@ -154,3 +156,58 @@ protected: return *(Bucket*)nullptr; } }; + +#else + +/// +/// Single-threaded version of thread local variable storage for basic types (POD). +/// +template +class ThreadLocal +{ +protected: + static_assert(TIsPODType::Value, "Only POD types are supported"); + + T _value; + bool _set = false; + +public: + ThreadLocal() + { + Platform::MemoryClear(&_value, sizeof(_value)); + _set = false; + } + +public: + FORCE_INLINE T& Get() + { + _set = true; + return _value; + } + + FORCE_INLINE void Set(const T& value) + { + _value = value; + _set = true; + } + + FORCE_INLINE int32 Count() const + { + return _set ? 1 : 0; + } + + template + FORCE_INLINE void GetValues(Array& result) const + { + if (_set) + result.Add(_value); + } + + FORCE_INLINE void Clear() + { + Platform::MemoryClear(&_value, sizeof(_value)); + _set = false; + } +}; + +#endif