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.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b79c9b9090..f8eec3b457 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -22,8 +22,10 @@ namespace LL { - class ThreadPool + class ThreadPool: public LLInstanceTracker { + private: + using super = LLInstanceTracker; public: /** * Pass ThreadPool a string name. This can be used to look up the -- 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.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index f8eec3b457..b49d511257 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -30,8 +30,17 @@ namespace LL /** * Pass ThreadPool a string name. This can be used to look up the * relevant WorkQueue. + * + * The number of threads you pass sets the compile-time default. But + * if the user has overridden the LLSD map in the "ThreadPoolSizes" + * setting with a key matching this ThreadPool name, that setting + * overrides this parameter. + * + * Pass an explicit capacity to limit the size of the queue. + * Constraining the queue can cause a submitter to block. Do not + * constrain any ThreadPool accepting work from the main thread. */ - ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); + ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024*1024); virtual ~ThreadPool(); /** @@ -59,6 +68,25 @@ namespace LL */ virtual void run(); + /** + * getConfiguredWidth() returns the setting, if any, for the specified + * ThreadPool name. Returns dft if the "ThreadPoolSizes" map does not + * contain the specified name. + */ + static + size_t getConfiguredWidth(const std::string& name, size_t dft=0); + + /** + * This getWidth() returns the width of the instantiated ThreadPool + * with the specified name, if any. If no instance exists, returns its + * getConfiguredWidth() if any. If there's no instance and no relevant + * override, return dft. Presumably dft should match the threads + * parameter passed to the ThreadPool constructor call that will + * eventually instantiate the ThreadPool with that name. + */ + static + size_t getWidth(const std::string& name, size_t dft); + private: void run(const std::string& name); -- cgit v1.2.3 From fc424a0db90fd2d2e44e85a19750ad6eaa57b28a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 9 Dec 2022 13:21:45 -0500 Subject: SL-18809: Add WorkSchedule; remove timestamps from WorkQueue. For work queues that don't need timestamped tasks, eliminate the overhead of a priority queue ordered by timestamp. Timestamped task support moves to WorkSchedule. WorkQueue is a simpler queue that just waits for work. Both WorkQueue and WorkSchedule can be accessed via new WorkQueueBase API. Of course the WorkQueueBase API doesn't deal with timestamps, but a WorkSchedule can be accessed directly to post timestamped tasks and then handled normally (e.g. by ThreadPool) to run them. Most ThreadPool functionality migrates to new ThreadPoolBase class, with template subclass ThreadPoolUsing or ThreadPoolUsing depending on need. ThreadPool is now an alias for ThreadPoolUsing. Importantly, ThreadPoolUsing::getQueue() delivers a reference to the specific queue subclass type, so you can post timestamped tasks on a queue retrieved from ThreadPoolUsing::getQueue(). Since ThreadPool is no longer a simple class but an alias for a particular template specialization, introduce threadpool_fwd.h to forward-declare it. Recast workqueue_test.cpp to exercise WorkSchedule, since some of the tests are time-based. A future todo would be to exercise each applicable test with both WorkQueue and WorkSchedule. --- indra/llcommon/threadpool.h | 60 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 12 deletions(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b49d511257..60f4a0ce1b 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -13,7 +13,9 @@ #if ! defined(LL_THREADPOOL_H) #define LL_THREADPOOL_H +#include "threadpool_fwd.h" #include "workqueue.h" +#include // std::unique_ptr #include #include #include // std::pair @@ -22,26 +24,24 @@ namespace LL { - class ThreadPool: public LLInstanceTracker + class ThreadPoolBase: public LLInstanceTracker { private: - using super = LLInstanceTracker; + using super = LLInstanceTracker; + public: /** - * Pass ThreadPool a string name. This can be used to look up the + * Pass ThreadPoolBase a string name. This can be used to look up the * relevant WorkQueue. * * The number of threads you pass sets the compile-time default. But * if the user has overridden the LLSD map in the "ThreadPoolSizes" * setting with a key matching this ThreadPool name, that setting * overrides this parameter. - * - * Pass an explicit capacity to limit the size of the queue. - * Constraining the queue can cause a submitter to block. Do not - * constrain any ThreadPool accepting work from the main thread. */ - ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024*1024); - virtual ~ThreadPool(); + ThreadPoolBase(const std::string& name, size_t threads, + WorkQueueBase* queue); + virtual ~ThreadPoolBase(); /** * Launch the ThreadPool. Until this call, a constructed ThreadPool @@ -59,8 +59,6 @@ namespace LL std::string getName() const { return mName; } size_t getWidth() const { return mThreads.size(); } - /// obtain a non-const reference to the WorkQueue to post work to it - WorkQueue& getQueue() { return mQueue; } /** * Override run() if you need special processing. The default run() @@ -87,15 +85,53 @@ namespace LL static size_t getWidth(const std::string& name, size_t dft); + protected: + std::unique_ptr mQueue; + private: void run(const std::string& name); - WorkQueue mQueue; std::string mName; size_t mThreadCount; std::vector> mThreads; }; + /** + * Specialize with WorkQueue or, for timestamped tasks, WorkSchedule + */ + template + struct ThreadPoolUsing: public ThreadPoolBase + { + using queue_t = QUEUE; + + /** + * Pass ThreadPoolUsing a string name. This can be used to look up the + * relevant WorkQueue. + * + * The number of threads you pass sets the compile-time default. But + * if the user has overridden the LLSD map in the "ThreadPoolSizes" + * setting with a key matching this ThreadPool name, that setting + * overrides this parameter. + * + * Pass an explicit capacity to limit the size of the queue. + * Constraining the queue can cause a submitter to block. Do not + * constrain any ThreadPool accepting work from the main thread. + */ + ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024): + ThreadPoolBase(name, threads, new queue_t(name, capacity)) + {} + ~ThreadPoolUsing() override {} + + /** + * obtain a non-const reference to the specific WorkQueue subclass to + * post work to it + */ + queue_t& getQueue() { return static_cast(*mQueue); } + }; + + /// ThreadPool is shorthand for using the simpler WorkQueue + using ThreadPool = ThreadPoolUsing; + } // namespace LL #endif /* ! defined(LL_THREADPOOL_H) */ -- cgit v1.2.3 From 4a34a1196627c7e9998edde725d5e839f3ef61b9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 20 Jan 2024 02:26:51 +0200 Subject: SL-18721 Shutdown fixes 1. After window closes viewer still takes some time to shut down, so added splash screen to not confuse users (and to see if something gets stuck) 2. Having two identical mWindowHandle caused confusion for me, so I split them. It looks like there might have been issues with thread being stuck because thread's handle wasn't cleaned up. 3. Made region clean mCacheMap immediately instead of spending time making copies on shutdown --- indra/llcommon/threadpool.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index 60f4a0ce1b..fa16c6fe71 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -40,7 +40,7 @@ namespace LL * overrides this parameter. */ ThreadPoolBase(const std::string& name, size_t threads, - WorkQueueBase* queue); + WorkQueueBase* queue, bool auto_shutdown = true); virtual ~ThreadPoolBase(); /** @@ -87,6 +87,7 @@ namespace LL protected: std::unique_ptr mQueue; + bool mAutomaticShutdown; private: void run(const std::string& name); @@ -117,8 +118,11 @@ namespace LL * Constraining the queue can cause a submitter to block. Do not * constrain any ThreadPool accepting work from the main thread. */ - ThreadPoolUsing(const std::string& name, size_t threads=1, size_t capacity=1024*1024): - ThreadPoolBase(name, threads, new queue_t(name, capacity)) + ThreadPoolUsing(const std::string& name, + size_t threads=1, + size_t capacity=1024*1024, + bool auto_shutdown = true): + ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown) {} ~ThreadPoolUsing() override {} -- cgit v1.2.3 From 2e5b105dffc41695d0a64c5b55eef7c28da49246 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 7 Feb 2024 22:50:28 +0200 Subject: SL-18721 Shutdown fixes #4 --- indra/llcommon/threadpool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index fa16c6fe71..b8be7bb81a 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -87,6 +87,7 @@ namespace LL protected: std::unique_ptr mQueue; + std::vector> mThreads; bool mAutomaticShutdown; private: @@ -94,7 +95,6 @@ namespace LL std::string mName; size_t mThreadCount; - std::vector> mThreads; }; /** -- cgit v1.2.3 From 1161262029f9619fb02d81575382b64d82d9cd09 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 15 Mar 2024 00:04:19 +0200 Subject: SL-18721 Restore release behavior Closing window correctly caused a significant amount of logout freezes with no known reproes. Temporarily returning to old behavior were thread was killes without closing window and will reenable in later maints to hopefully get a scenario or at least more data of what is causing the freeze. --- indra/llcommon/threadpool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/threadpool.h') diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index b8be7bb81a..74056aea17 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -55,7 +55,7 @@ namespace LL * ThreadPool listens for application shutdown messages on the "LLApp" * LLEventPump. Call close() to shut down this ThreadPool early. */ - void close(); + virtual void close(); std::string getName() const { return mName; } size_t getWidth() const { return mThreads.size(); } -- cgit v1.2.3