cmWorkerPool.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #ifndef cmWorkerPool_h
  4. #define cmWorkerPool_h
  5. #include "cmConfigure.h" // IWYU pragma: keep
  6. #include "cmAlgorithms.h" // IWYU pragma: keep
  7. #include <memory>
  8. #include <stdint.h>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. // -- Types
  13. class cmWorkerPoolInternal;
  14. /** @class cmWorkerPool
  15. * @brief Thread pool with job queue
  16. */
  17. class cmWorkerPool
  18. {
  19. public:
  20. /**
  21. * Return value and output of an external process.
  22. */
  23. struct ProcessResultT
  24. {
  25. void reset();
  26. bool error() const
  27. {
  28. return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
  29. }
  30. std::int64_t ExitStatus = 0;
  31. int TermSignal = 0;
  32. std::string StdOut;
  33. std::string StdErr;
  34. std::string ErrorMessage;
  35. };
  36. /**
  37. * Abstract job class for concurrent job processing.
  38. */
  39. class JobT
  40. {
  41. public:
  42. JobT(JobT const&) = delete;
  43. JobT& operator=(JobT const&) = delete;
  44. /**
  45. * Virtual destructor.
  46. */
  47. virtual ~JobT();
  48. /**
  49. * Fence job flag
  50. *
  51. * Fence jobs require that:
  52. * - all jobs before in the queue have been processed
  53. * - no jobs later in the queue will be processed before this job was
  54. * processed
  55. */
  56. bool IsFence() const { return Fence_; }
  57. protected:
  58. /**
  59. * Protected default constructor
  60. */
  61. JobT(bool fence = false)
  62. : Fence_(fence)
  63. {
  64. }
  65. /**
  66. * Abstract processing interface that must be implement in derived classes.
  67. */
  68. virtual void Process() = 0;
  69. /**
  70. * Get the worker pool.
  71. * Only valid during the JobT::Process() call!
  72. */
  73. cmWorkerPool* Pool() const { return Pool_; }
  74. /**
  75. * Get the user data.
  76. * Only valid during the JobT::Process() call!
  77. */
  78. void* UserData() const { return Pool_->UserData(); };
  79. /**
  80. * Get the worker index.
  81. * This is the index of the thread processing this job and is in the range
  82. * [0..ThreadCount).
  83. * Concurrently processing jobs will never have the same WorkerIndex().
  84. * Only valid during the JobT::Process() call!
  85. */
  86. unsigned int WorkerIndex() const { return WorkerIndex_; }
  87. /**
  88. * Run an external read only process.
  89. * Use only during JobT::Process() call!
  90. */
  91. bool RunProcess(ProcessResultT& result,
  92. std::vector<std::string> const& command,
  93. std::string const& workingDirectory);
  94. private:
  95. //! Needs access to Work()
  96. friend class cmWorkerPoolInternal;
  97. //! Worker thread entry method.
  98. void Work(cmWorkerPool* pool, unsigned int workerIndex)
  99. {
  100. Pool_ = pool;
  101. WorkerIndex_ = workerIndex;
  102. this->Process();
  103. }
  104. private:
  105. cmWorkerPool* Pool_ = nullptr;
  106. unsigned int WorkerIndex_ = 0;
  107. bool Fence_ = false;
  108. };
  109. /**
  110. * Job handle type
  111. */
  112. typedef std::unique_ptr<JobT> JobHandleT;
  113. /**
  114. * Fence job base class
  115. */
  116. class JobFenceT : public JobT
  117. {
  118. public:
  119. JobFenceT()
  120. : JobT(true)
  121. {
  122. }
  123. //! Does nothing
  124. void Process() override{};
  125. };
  126. /**
  127. * Fence job that aborts the worker pool.
  128. *
  129. * Useful as the last job in the job queue.
  130. */
  131. class JobEndT : JobFenceT
  132. {
  133. public:
  134. //! Does nothing
  135. void Process() override { Pool()->Abort(); }
  136. };
  137. public:
  138. // -- Methods
  139. cmWorkerPool();
  140. ~cmWorkerPool();
  141. /**
  142. * Number of worker threads.
  143. */
  144. unsigned int ThreadCount() const { return ThreadCount_; }
  145. /**
  146. * Set the number of worker threads.
  147. *
  148. * Calling this method during Process() has no effect.
  149. */
  150. void SetThreadCount(unsigned int threadCount);
  151. /**
  152. * Blocking function that starts threads to process all Jobs in the queue.
  153. *
  154. * This method blocks until a job calls the Abort() method.
  155. * @arg threadCount Number of threads to process jobs.
  156. * @arg userData Common user data pointer available in all Jobs.
  157. */
  158. bool Process(void* userData = nullptr);
  159. /**
  160. * User data reference passed to Process().
  161. *
  162. * Only valid during Process().
  163. */
  164. void* UserData() const { return UserData_; }
  165. // -- Job processing interface
  166. /**
  167. * Clears the job queue and aborts all worker threads.
  168. *
  169. * This method is thread safe and can be called from inside a job.
  170. */
  171. void Abort();
  172. /**
  173. * Push job to the queue.
  174. *
  175. * This method is thread safe and can be called from inside a job or before
  176. * Process().
  177. */
  178. bool PushJob(JobHandleT&& jobHandle);
  179. /**
  180. * Push job to the queue
  181. *
  182. * This method is thread safe and can be called from inside a job or before
  183. * Process().
  184. */
  185. template <class T, typename... Args>
  186. bool EmplaceJob(Args&&... args)
  187. {
  188. return PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
  189. }
  190. private:
  191. void* UserData_ = nullptr;
  192. unsigned int ThreadCount_ = 1;
  193. std::unique_ptr<cmWorkerPoolInternal> Int_;
  194. };
  195. #endif