From 68b3382ef7e0f7795b9a601aae73adc2f8ef9873 Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Wed, 29 Nov 2023 09:14:57 -0500 Subject: global thread worker pools (#577) - Improvement: Use two global worker thread pools instead of ad-hoc creation of worker pools --- src/zenutil/workerpools.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/zenutil/workerpools.cpp (limited to 'src/zenutil/workerpools.cpp') diff --git a/src/zenutil/workerpools.cpp b/src/zenutil/workerpools.cpp new file mode 100644 index 000000000..b511b0c5c --- /dev/null +++ b/src/zenutil/workerpools.cpp @@ -0,0 +1,89 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include "zenutil/workerpools.h" + +#include +#include + +ZEN_THIRD_PARTY_INCLUDES_START +#include +ZEN_THIRD_PARTY_INCLUDES_END + +namespace zen { +namespace { + const int LargeWorkerThreadPoolTreadCount = gsl::narrow(std::thread::hardware_concurrency()); + const int SmallWorkerThreadPoolTreadCount = gsl::narrow(Max((std::thread::hardware_concurrency() / 4u), 1u)); + + RwLock PoolLock; + + std::unique_ptr LargeWorkerPool; + std::unique_ptr SmallWorkerPool; + std::unique_ptr SyncWorkerPool; +} // namespace + +WorkerThreadPool& +GetLargeWorkerPool() +{ + { + RwLock::SharedLockScope _(PoolLock); + if (LargeWorkerPool) + { + return *LargeWorkerPool; + } + } + RwLock::ExclusiveLockScope _(PoolLock); + if (LargeWorkerPool) + { + return *LargeWorkerPool; + } + LargeWorkerPool.reset(new WorkerThreadPool(LargeWorkerThreadPoolTreadCount, "LargeThreadPool")); + return *LargeWorkerPool; +} + +WorkerThreadPool& +GetSmallWorkerPool() +{ + { + RwLock::SharedLockScope _(PoolLock); + if (SmallWorkerPool) + { + return *SmallWorkerPool; + } + } + RwLock::ExclusiveLockScope _(PoolLock); + if (SmallWorkerPool) + { + return *SmallWorkerPool; + } + SmallWorkerPool.reset(new WorkerThreadPool(SmallWorkerThreadPoolTreadCount, "SmallThreadPool")); + return *SmallWorkerPool; +} + +WorkerThreadPool& +GetSyncWorkerPool() +{ + { + RwLock::SharedLockScope _(PoolLock); + if (SyncWorkerPool) + { + return *SyncWorkerPool; + } + } + RwLock::ExclusiveLockScope _(PoolLock); + if (SyncWorkerPool) + { + return *SyncWorkerPool; + } + SyncWorkerPool.reset(new WorkerThreadPool(0, "SyncThreadPool")); + return *SyncWorkerPool; +} + +void +ShutdownWorkerPools() +{ + RwLock::ExclusiveLockScope _(PoolLock); + LargeWorkerPool.reset(); + SmallWorkerPool.reset(); + SyncWorkerPool.reset(); +} +} // namespace zen -- cgit v1.2.3 From aeecf717fee464ac2b9700e571d19c0c51794d7b Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Mon, 4 Dec 2023 05:16:22 -0500 Subject: safe threadpool shutdown (#584) * shut down thread pools earlier to worker threads has a chance to terminate before main thread atexit --- src/zenutil/workerpools.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/zenutil/workerpools.cpp') diff --git a/src/zenutil/workerpools.cpp b/src/zenutil/workerpools.cpp index b511b0c5c..3ae302064 100644 --- a/src/zenutil/workerpools.cpp +++ b/src/zenutil/workerpools.cpp @@ -14,6 +14,8 @@ namespace { const int LargeWorkerThreadPoolTreadCount = gsl::narrow(std::thread::hardware_concurrency()); const int SmallWorkerThreadPoolTreadCount = gsl::narrow(Max((std::thread::hardware_concurrency() / 4u), 1u)); + static bool IsShutDown = false; + RwLock PoolLock; std::unique_ptr LargeWorkerPool; @@ -32,6 +34,7 @@ GetLargeWorkerPool() } } RwLock::ExclusiveLockScope _(PoolLock); + ZEN_ASSERT(!IsShutDown); if (LargeWorkerPool) { return *LargeWorkerPool; @@ -51,6 +54,7 @@ GetSmallWorkerPool() } } RwLock::ExclusiveLockScope _(PoolLock); + ZEN_ASSERT(!IsShutDown); if (SmallWorkerPool) { return *SmallWorkerPool; @@ -70,6 +74,7 @@ GetSyncWorkerPool() } } RwLock::ExclusiveLockScope _(PoolLock); + ZEN_ASSERT(!IsShutDown); if (SyncWorkerPool) { return *SyncWorkerPool; @@ -82,6 +87,7 @@ void ShutdownWorkerPools() { RwLock::ExclusiveLockScope _(PoolLock); + IsShutDown = true; LargeWorkerPool.reset(); SmallWorkerPool.reset(); SyncWorkerPool.reset(); -- cgit v1.2.3