CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmWorkerPool.h
blob40356501632b1f2dfbc21f914f7527b4b694e77f
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #pragma once
5 #include "cmConfigure.h" // IWYU pragma: keep
7 #include <cstdint>
8 #include <string>
9 #include <utility>
10 #include <vector>
12 #include <cm/memory>
14 // -- Types
15 class cmWorkerPoolInternal;
17 /** @class cmWorkerPool
18 * @brief Thread pool with job queue
20 class cmWorkerPool
22 public:
23 /**
24 * Return value and output of an external process.
26 struct ProcessResultT
28 void reset();
29 bool error() const
31 return (this->ExitStatus != 0) || (this->TermSignal != 0) ||
32 !this->ErrorMessage.empty();
35 std::int64_t ExitStatus = 0;
36 int TermSignal = 0;
37 std::string StdOut;
38 std::string StdErr;
39 std::string ErrorMessage;
42 /**
43 * Abstract job class for concurrent job processing.
45 class JobT
47 public:
48 JobT(JobT const&) = delete;
49 JobT& operator=(JobT const&) = delete;
51 /**
52 * Virtual destructor.
54 virtual ~JobT();
56 /**
57 * Fence job flag
59 * Fence jobs require that:
60 * - all jobs before in the queue have been processed
61 * - no jobs later in the queue will be processed before this job was
62 * processed
64 bool IsFence() const { return this->Fence_; }
66 protected:
67 /**
68 * Protected default constructor
70 JobT(bool fence = false)
71 : Fence_(fence)
75 /**
76 * Abstract processing interface that must be implement in derived classes.
78 virtual void Process() = 0;
80 /**
81 * Get the worker pool.
82 * Only valid during the JobT::Process() call!
84 cmWorkerPool* Pool() const { return this->Pool_; }
86 /**
87 * Get the user data.
88 * Only valid during the JobT::Process() call!
90 void* UserData() const { return this->Pool_->UserData(); }
92 /**
93 * Get the worker index.
94 * This is the index of the thread processing this job and is in the range
95 * [0..ThreadCount).
96 * Concurrently processing jobs will never have the same WorkerIndex().
97 * Only valid during the JobT::Process() call!
99 unsigned int WorkerIndex() const { return this->WorkerIndex_; }
102 * Run an external read only process.
103 * Use only during JobT::Process() call!
105 bool RunProcess(ProcessResultT& result,
106 std::vector<std::string> const& command,
107 std::string const& workingDirectory);
109 private:
110 //! Needs access to Work()
111 friend class cmWorkerPoolInternal;
112 //! Worker thread entry method.
113 void Work(cmWorkerPool* pool, unsigned int workerIndex)
115 this->Pool_ = pool;
116 this->WorkerIndex_ = workerIndex;
117 this->Process();
120 cmWorkerPool* Pool_ = nullptr;
121 unsigned int WorkerIndex_ = 0;
122 bool Fence_ = false;
126 * Job handle type
128 using JobHandleT = std::unique_ptr<JobT>;
131 * Fence job base class
133 class JobFenceT : public JobT
135 public:
136 JobFenceT()
137 : JobT(true)
140 //! Does nothing
141 void Process() override {}
145 * Fence job that aborts the worker pool.
147 * Useful as the last job in the job queue.
149 class JobEndT : JobFenceT
151 public:
152 //! Does nothing
153 void Process() override { this->Pool()->Abort(); }
156 // -- Methods
157 cmWorkerPool();
158 ~cmWorkerPool();
161 * Number of worker threads.
163 unsigned int ThreadCount() const { return this->ThreadCount_; }
166 * Set the number of worker threads.
168 * Calling this method during Process() has no effect.
170 void SetThreadCount(unsigned int threadCount);
173 * Blocking function that starts threads to process all Jobs in the queue.
175 * This method blocks until a job calls the Abort() method.
176 * @arg threadCount Number of threads to process jobs.
177 * @arg userData Common user data pointer available in all Jobs.
179 bool Process(void* userData = nullptr);
182 * User data reference passed to Process().
184 * Only valid during Process().
186 void* UserData() const { return this->UserData_; }
188 // -- Job processing interface
191 * Clears the job queue and aborts all worker threads.
193 * This method is thread safe and can be called from inside a job.
195 void Abort();
198 * Push job to the queue.
200 * This method is thread safe and can be called from inside a job or before
201 * Process().
203 bool PushJob(JobHandleT&& jobHandle);
206 * Push job to the queue
208 * This method is thread safe and can be called from inside a job or before
209 * Process().
211 template <class T, typename... Args>
212 bool EmplaceJob(Args&&... args)
214 return this->PushJob(cm::make_unique<T>(std::forward<Args>(args)...));
217 private:
218 void* UserData_ = nullptr;
219 unsigned int ThreadCount_ = 1;
220 std::unique_ptr<cmWorkerPoolInternal> Int_;