llthreadpool.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /**
  2. * @file llthreadpool.h
  3. * @brief Configures a LLWorkQueue along with a pool of threads to service it.
  4. * @author Nat Goodspeed
  5. * @date 2021-10-21
  6. *
  7. * $LicenseInfo:firstyear=2021&license=viewergpl$
  8. *
  9. * Copyright (c) 2021, Linden Research, Inc. (c) 2022 Henri Beauchamp.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #ifndef LL_THREADPOOL_H
  35. #define LL_THREADPOOL_H
  36. #include "hbfastmap.h"
  37. #include "llworkqueue.h"
  38. class LLThreadPool
  39. {
  40. protected:
  41. LOG_CLASS(LLThreadPool);
  42. public:
  43. // LLThreadPool takes a string name. This can be used to look up the
  44. // relevant LLWorkQueue.
  45. LLThreadPool(const std::string& name, U32 threads = 1,
  46. // The default capacity is huge to avoid blocking the main
  47. // thread due to a starvation.
  48. U32 capacity = 1024 * 1024);
  49. virtual ~LLThreadPool() = default;
  50. // Launch the LLThreadPool. Until this call, a constructed LLThreadPool
  51. // launches no threads. That permits coders to derive from LLThreadPool,
  52. // or store it as a member of some other class, but refrain from launching
  53. // it until all other construction is complete.
  54. // If wait_for_start is true, wait until all threads have actually started
  55. // before returning to the caller. HB
  56. void start(bool wait_for_start = false);
  57. // LLThreadPool listens for application shutdown messages on the "LLApp"
  58. // LLEventPump. Call close() to shut down this LLThreadPool early. Note
  59. // that this is a wrapper to the "real" close(), so that the "on_shutdown"
  60. // and "on_crash" booleans cannot be wrongly used in the latter. HB
  61. LL_INLINE void close() { close(false, false); }
  62. LL_INLINE const std::string& getName() const { return mName; }
  63. LL_INLINE U32 getWidth() const { return mThreads.size(); }
  64. // Number of threads used to service the queue. HB
  65. LL_INLINE U32 getThreadsCount() const { return mThreadCount; }
  66. // Number of threads actually and currently started. HB
  67. LL_INLINE U32 getStartedThreads() { return mStartedThreads; }
  68. // Override this if you do not want your thread to be accounted as
  69. // "started" by LLThreadPool::run(const std::string& name) before some
  70. // initialization work is fully performed in your own run() method; in this
  71. // case, simply override this with a no-op method, and do call the second,
  72. // non overridable method below when appropriate in your overriden run()
  73. // method. HB
  74. LL_INLINE virtual void maybeIncStartedThreads() { ++mStartedThreads; }
  75. LL_INLINE void doIncStartedThreads() { ++mStartedThreads; }
  76. // Returns the name for a thread with a given thread Id hash, or "invalid"
  77. // when that hash is not found. HB
  78. const std::string& getThreadName(U64 id_hash);
  79. // Obtains a non-const reference to the LLWorkQueue to post work to it.
  80. LL_INLINE LLWorkQueue& getQueue() { return mQueue; }
  81. // Override run() if you need special processing. The default run()
  82. // implementation simply calls LLWorkQueue::runUntilClose().
  83. virtual void run();
  84. private:
  85. void close(bool on_shutdown, bool on_crash);
  86. void run(const std::string& name);
  87. void closeOnShutdown();
  88. private:
  89. LLWorkQueue mQueue;
  90. std::string mName;
  91. #if TRACY_ENABLE
  92. const char* mThreadPoolName;
  93. #endif
  94. typedef std::vector<std::pair<std::string, boost::thread> > threads_list_t;
  95. threads_list_t mThreads;
  96. LLMutex mThreadNamesMutex;
  97. typedef safe_hmap<U64, std::string> tnames_map_t;
  98. tnames_map_t mThreadNames;
  99. // mStartedThreads is incremented each time a new thread is actually
  100. // started since threads launch is itself a threaded operation; thus why
  101. // we also must use an atomic counter here. HB
  102. LLAtomicU32 mStartedThreads;
  103. U32 mThreadCount;
  104. };
  105. #endif // LL_THREADPOOL_H