From ef87eb7fa80a72b94d67d5ab680f60a837dd1ddd Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Tue, 31 May 2022 12:49:53 -0700 Subject: SL-17483: Make ThreadPool inherit LLInstanceTracker (cherry picked from commit 41d6a0e222241606c317281e2f0b211e16813dd5) --- indra/llcommon/threadpool.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index ba914035e2..d5adf11264 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -22,6 +22,7 @@ #include "stringize.h" LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): + super(name), mQueue(name, capacity), mName("ThreadPool:" + name), mThreadCount(threads) -- cgit v1.2.3 From ac99e979f43d49402a24b2f58a154c4ef1583efd Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 9 Jun 2022 10:18:29 -0400 Subject: SL-17483: Make it possible to override width of any ThreadPool. Introduce CommonControl, which in a running viewer (or any program containing an LLViewerControlListener instance) gives access to LLViewerControl functionality, e.g. getting, setting or enumerating control variables -- without introducing a link dependency on newview. Make ThreadPool's constructor consult CommonControl to check for an override for the width of the new ThreadPool in the Global (i.e. gSavedSettings) setting ThreadPoolSizes, and honor that if found. Introduce static ThreadPool methods getConfiguredWidth(), to query for such an override on any particular ThreadPool name; and getWidth(), to ask for the width of an instance if that instance already exists, else the width with which it *would* be instantiated. --- indra/llcommon/threadpool.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index d5adf11264..10d67abf37 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -17,15 +17,17 @@ // std headers // external library headers // other Linden headers +#include "commoncontrol.h" #include "llerror.h" #include "llevents.h" +#include "llsd.h" #include "stringize.h" LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): super(name), mQueue(name, capacity), mName("ThreadPool:" + name), - mThreadCount(threads) + mThreadCount(getConfiguredWidth(name, threads)) {} void LL::ThreadPool::start() @@ -87,3 +89,50 @@ void LL::ThreadPool::run() { mQueue.runUntilClose(); } + +//static +size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft=0) +{ + LLSD poolSizes{ LL::CommonControl::get("Global", "ThreadPoolSizes") }; + // "ThreadPoolSizes" is actually a map containing the sizes of interest -- + // or should be, if this process has an "LLViewerControl" LLEventAPI + // instance and its settings include "ThreadPoolSizes". If we failed to + // retrieve it, perhaps we're in a program that doesn't define that, or + // perhaps there's no such setting, or perhaps we're asking too early, + // before the LLEventAPI itself has been instantiated. In any of those + // cases, it seems worth warning. + if (! poolSizes.isDefined()) + { + // Note: we don't warn about absence of an override key for a + // particular ThreadPool name, that's fine. This warning is about + // complete absence of a ThreadPoolSizes setting, which we expect in a + // normal viewer session. + LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '" + << name << "'" << LL_ENDL; + } + else + { + //LL_DEBUGS + LL_INFOS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; + } + // LLSD treats an undefined value as an empty map when asked to retrieve a + // key, so we don't need this to be conditional. + LLSD sizeSpec{ poolSizes[name] }; + // We retrieve sizeSpec as LLSD, rather than immediately as LLSD::Integer, + // so we can distinguish the case when it's undefined. + return sizeSpec.isInteger() ? sizeSpec.asInteger() : dft; +} + +//static +size_t LL::ThreadPool::getWidth(const std::string& name, size_t dft) +{ + auto instance{ getInstance(name) }; + if (instance) + { + return instance->getWidth(); + } + else + { + return getConfiguredWidth(name, dft); + } +} -- cgit v1.2.3 From 1ff79a430d9d55cbb4b4ba55018c791a8a933916 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 9 Jun 2022 11:19:21 -0400 Subject: SL-17483: Fix ThreadPool::getConfiguredWidth() compile error. Log ThreadPoolSizes at DEBUG level, not INFO. --- indra/llcommon/threadpool.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index 10d67abf37..e8daf549ef 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -91,7 +91,7 @@ void LL::ThreadPool::run() } //static -size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft=0) +size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft) { LLSD poolSizes{ LL::CommonControl::get("Global", "ThreadPoolSizes") }; // "ThreadPoolSizes" is actually a map containing the sizes of interest -- @@ -112,8 +112,7 @@ size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft=0) } else { - //LL_DEBUGS - LL_INFOS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; + LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; } // LLSD treats an undefined value as an empty map when asked to retrieve a // key, so we don't need this to be conditional. -- cgit v1.2.3 From 64209ddeeafd944f82da6f13a6e790f9b542b3ff Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 9 Jun 2022 17:04:26 -0400 Subject: SL-17483: Add integration test for CommonControl and for LLViewerControlListener, to which it talks. Fix glitches detected by the tests. --- indra/llcommon/threadpool.cpp | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) (limited to 'indra/llcommon/threadpool.cpp') diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index e8daf549ef..f49dd40a8b 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -93,27 +93,36 @@ void LL::ThreadPool::run() //static size_t LL::ThreadPool::getConfiguredWidth(const std::string& name, size_t dft) { - LLSD poolSizes{ LL::CommonControl::get("Global", "ThreadPoolSizes") }; - // "ThreadPoolSizes" is actually a map containing the sizes of interest -- - // or should be, if this process has an "LLViewerControl" LLEventAPI - // instance and its settings include "ThreadPoolSizes". If we failed to - // retrieve it, perhaps we're in a program that doesn't define that, or - // perhaps there's no such setting, or perhaps we're asking too early, - // before the LLEventAPI itself has been instantiated. In any of those - // cases, it seems worth warning. - if (! poolSizes.isDefined()) + LLSD poolSizes; + try { - // Note: we don't warn about absence of an override key for a - // particular ThreadPool name, that's fine. This warning is about - // complete absence of a ThreadPoolSizes setting, which we expect in a - // normal viewer session. - LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '" - << name << "'" << LL_ENDL; + poolSizes = LL::CommonControl::get("Global", "ThreadPoolSizes"); + // "ThreadPoolSizes" is actually a map containing the sizes of + // interest -- or should be, if this process has an + // LLViewerControlListener instance and its settings include + // "ThreadPoolSizes". If we failed to retrieve it, perhaps we're in a + // program that doesn't define that, or perhaps there's no such + // setting, or perhaps we're asking too early, before the LLEventAPI + // itself has been instantiated. In any of those cases, it seems worth + // warning. + if (! poolSizes.isDefined()) + { + // Note: we don't warn about absence of an override key for a + // particular ThreadPool name, that's fine. This warning is about + // complete absence of a ThreadPoolSizes setting, which we expect + // in a normal viewer session. + LL_WARNS("ThreadPool") << "No 'ThreadPoolSizes' setting for ThreadPool '" + << name << "'" << LL_ENDL; + } } - else + catch (const LL::CommonControl::Error& exc) { - LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; + // We don't want ThreadPool to *require* LLViewerControlListener. + // Just log it and carry on. + LL_WARNS("ThreadPool") << "Can't check 'ThreadPoolSizes': " << exc.what() << LL_ENDL; } + + LL_DEBUGS("ThreadPool") << "ThreadPoolSizes = " << poolSizes << LL_ENDL; // LLSD treats an undefined value as an empty map when asked to retrieve a // key, so we don't need this to be conditional. LLSD sizeSpec{ poolSizes[name] }; -- cgit v1.2.3