3346 |
06 Nov 14 |
peter |
1 |
#ifndef theplu_yat_utility_scheduler |
3346 |
06 Nov 14 |
peter |
2 |
#define theplu_yat_utility_scheduler |
3346 |
06 Nov 14 |
peter |
3 |
|
3346 |
06 Nov 14 |
peter |
// $Id$ |
3346 |
06 Nov 14 |
peter |
5 |
|
3346 |
06 Nov 14 |
peter |
6 |
/* |
3855 |
02 Jan 20 |
peter |
Copyright (C) 2014, 2015, 2016, 2017, 2019, 2020 Peter Johansson |
3346 |
06 Nov 14 |
peter |
8 |
|
3346 |
06 Nov 14 |
peter |
This file is part of the yat library, http://dev.thep.lu.se/yat |
3346 |
06 Nov 14 |
peter |
10 |
|
3346 |
06 Nov 14 |
peter |
The yat library is free software; you can redistribute it and/or |
3346 |
06 Nov 14 |
peter |
modify it under the terms of the GNU General Public License as |
3346 |
06 Nov 14 |
peter |
published by the Free Software Foundation; either version 3 of the |
3346 |
06 Nov 14 |
peter |
License, or (at your option) any later version. |
3346 |
06 Nov 14 |
peter |
15 |
|
3346 |
06 Nov 14 |
peter |
The yat library is distributed in the hope that it will be useful, |
3346 |
06 Nov 14 |
peter |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
3346 |
06 Nov 14 |
peter |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3346 |
06 Nov 14 |
peter |
General Public License for more details. |
3346 |
06 Nov 14 |
peter |
20 |
|
3346 |
06 Nov 14 |
peter |
You should have received a copy of the GNU General Public License |
3346 |
06 Nov 14 |
peter |
along with yat. If not, see <http://www.gnu.org/licenses/>. |
3346 |
06 Nov 14 |
peter |
23 |
*/ |
3346 |
06 Nov 14 |
peter |
24 |
|
3402 |
31 Mar 15 |
peter |
25 |
#include "PriorityQueue.h" |
3346 |
06 Nov 14 |
peter |
26 |
#include "Queue.h" |
3346 |
06 Nov 14 |
peter |
27 |
|
3405 |
06 Apr 15 |
peter |
28 |
#include <boost/exception_ptr.hpp> |
3346 |
06 Nov 14 |
peter |
29 |
#include <boost/shared_ptr.hpp> |
3346 |
06 Nov 14 |
peter |
30 |
|
3848 |
23 Sep 19 |
peter |
31 |
#include <list> |
3948 |
20 Jul 20 |
peter |
32 |
#include <mutex> |
3346 |
06 Nov 14 |
peter |
33 |
#include <set> |
3948 |
20 Jul 20 |
peter |
34 |
#include <thread> |
3848 |
23 Sep 19 |
peter |
35 |
#include <vector> |
3346 |
06 Nov 14 |
peter |
36 |
|
3346 |
06 Nov 14 |
peter |
37 |
namespace theplu { |
3346 |
06 Nov 14 |
peter |
38 |
namespace yat { |
3346 |
06 Nov 14 |
peter |
39 |
namespace utility { |
3346 |
06 Nov 14 |
peter |
40 |
|
3346 |
06 Nov 14 |
peter |
41 |
/** |
3346 |
06 Nov 14 |
peter |
\brief Handle a number of jobs and send them to threads |
3346 |
06 Nov 14 |
peter |
43 |
|
3346 |
06 Nov 14 |
peter |
Scheduler starts a (user defined) number of threads and handles a |
3346 |
06 Nov 14 |
peter |
series of Jobs. The Jobs can have dependencies, such that Job X |
3346 |
06 Nov 14 |
peter |
must finish before Job Y can run, and the Scheduler takes care of |
3402 |
31 Mar 15 |
peter |
these dependencies. Here is a small code example in which two |
3346 |
06 Nov 14 |
peter |
threads are used to process the four jobs, \c MyJob. The jobs |
3346 |
06 Nov 14 |
peter |
have a dependency that job4 can not run until the three first |
3346 |
06 Nov 14 |
peter |
jobs have completed. |
3346 |
06 Nov 14 |
peter |
51 |
|
3346 |
06 Nov 14 |
peter |
\code |
3346 |
06 Nov 14 |
peter |
53 |
|
3346 |
06 Nov 14 |
peter |
Scheduler scheduler(2); |
3346 |
06 Nov 14 |
peter |
boost::shared_ptr<MyJob> job1(new MyJob("Hello")); |
3401 |
31 Mar 15 |
peter |
boost::shared_ptr<MyJob> job2(new MyJob(" ")); |
3346 |
06 Nov 14 |
peter |
boost::shared_ptr<MyJob> job3(new MyJob("World")); |
3346 |
06 Nov 14 |
peter |
boost::shared_ptr<MyJob> job4(new MyJob("\n")); |
3401 |
31 Mar 15 |
peter |
scheduler.add_dependency(job4, job1); |
3401 |
31 Mar 15 |
peter |
scheduler.add_dependency(job4, job2); |
3401 |
31 Mar 15 |
peter |
scheduler.add_dependency(job4, job3); |
3346 |
06 Nov 14 |
peter |
scheduler.submit(job4); |
3402 |
31 Mar 15 |
peter |
scheduler.wait(); |
3346 |
06 Nov 14 |
peter |
64 |
|
3346 |
06 Nov 14 |
peter |
\endcode |
3402 |
31 Mar 15 |
peter |
66 |
|
3402 |
31 Mar 15 |
peter |
The Scheduler sends jobs to the workers taking into account |
3402 |
31 Mar 15 |
peter |
dependencies, priorities and the order in which the Scheduler has |
3683 |
22 Aug 17 |
peter |
seen the Jobs. If the Jobs that are ready to run, i.e., all jobs |
3683 |
22 Aug 17 |
peter |
it depends on have completed, the Scheduler choose the Job with |
3402 |
31 Mar 15 |
peter |
highest priority. If two Jobs have the same priority, the |
3402 |
31 Mar 15 |
peter |
Scheduler sends them in the order of appearance, i.e., if the |
3402 |
31 Mar 15 |
peter |
Scheduler saw Job X before Job Y, Job X is run before Job X. |
3402 |
31 Mar 15 |
peter |
74 |
|
3406 |
07 Apr 15 |
peter |
\note In the current implementation all submitted jobs have |
3406 |
07 Apr 15 |
peter |
to be completed before the Scheduler goes out of scope, which can |
3406 |
07 Apr 15 |
peter |
be accomplished by calling wait() or interrupt(). |
3406 |
07 Apr 15 |
peter |
78 |
|
3828 |
23 Jul 19 |
peter |
\note Prior version 0.17 the Scheduler could not be recycled, i.e., |
3828 |
23 Jul 19 |
peter |
if wait(void) or interruped(void) had been called, the behaviour of |
3828 |
23 Jul 19 |
peter |
submit() was undefined. |
3406 |
07 Apr 15 |
peter |
82 |
|
3402 |
31 Mar 15 |
peter |
\since New in yat 0.13 |
3346 |
06 Nov 14 |
peter |
84 |
*/ |
3346 |
06 Nov 14 |
peter |
85 |
class Scheduler |
3346 |
06 Nov 14 |
peter |
86 |
{ |
3346 |
06 Nov 14 |
peter |
87 |
public: |
3346 |
06 Nov 14 |
peter |
88 |
/** |
3346 |
06 Nov 14 |
peter |
Base class that defines the interface for a Job |
3346 |
06 Nov 14 |
peter |
90 |
*/ |
3346 |
06 Nov 14 |
peter |
91 |
class Job |
3346 |
06 Nov 14 |
peter |
92 |
{ |
3346 |
06 Nov 14 |
peter |
93 |
public: |
3346 |
06 Nov 14 |
peter |
94 |
/** |
3346 |
06 Nov 14 |
peter |
\brief constructor |
3848 |
23 Sep 19 |
peter |
\param prio sets the priority. Jobs with greater priority are |
3848 |
23 Sep 19 |
peter |
run before jobs with lower priority (when possible). |
3346 |
06 Nov 14 |
peter |
98 |
*/ |
3402 |
31 Mar 15 |
peter |
99 |
explicit Job(unsigned int prio=0); |
3346 |
06 Nov 14 |
peter |
100 |
|
3346 |
06 Nov 14 |
peter |
101 |
/** |
3346 |
06 Nov 14 |
peter |
\brief destructor |
3346 |
06 Nov 14 |
peter |
103 |
*/ |
3346 |
06 Nov 14 |
peter |
104 |
virtual ~Job(void); |
3346 |
06 Nov 14 |
peter |
105 |
|
3346 |
06 Nov 14 |
peter |
106 |
/** |
3402 |
31 Mar 15 |
peter |
Jobs with greater priority are run before Jobs with less priority. |
3402 |
31 Mar 15 |
peter |
108 |
*/ |
3402 |
31 Mar 15 |
peter |
109 |
unsigned int priority(void) const; |
3402 |
31 Mar 15 |
peter |
110 |
|
3402 |
31 Mar 15 |
peter |
111 |
/** |
3346 |
06 Nov 14 |
peter |
This function defines the work done in thread. |
3346 |
06 Nov 14 |
peter |
113 |
*/ |
3346 |
06 Nov 14 |
peter |
114 |
virtual void operator()(void)=0; |
3346 |
06 Nov 14 |
peter |
115 |
private: |
3346 |
06 Nov 14 |
peter |
116 |
friend class Scheduler; |
3681 |
22 Aug 17 |
peter |
117 |
friend class JobHandler; |
3853 |
01 Jan 20 |
peter |
118 |
void add_prerequisite(const boost::shared_ptr<Job>&, |
3948 |
20 Jul 20 |
peter |
119 |
const std::unique_lock<std::mutex>& lock); |
3681 |
22 Aug 17 |
peter |
// \brief remove job from list of prerequisite |
3681 |
22 Aug 17 |
peter |
// \return number of prerequisite (after removal) |
3853 |
01 Jan 20 |
peter |
122 |
size_t remove_prerequisite(const boost::shared_ptr<Job>&, |
3948 |
20 Jul 20 |
peter |
123 |
const std::unique_lock<std::mutex>& lock); |
3346 |
06 Nov 14 |
peter |
// set of jobs that have to finish before this can run |
3401 |
31 Mar 15 |
peter |
125 |
std::set<boost::shared_ptr<Job> > prerequisite_; |
3853 |
01 Jan 20 |
peter |
// avoid accessing prerequisite_ directly but rather via |
3853 |
01 Jan 20 |
peter |
// functions below passing Dependency::Lock |
3853 |
01 Jan 20 |
peter |
128 |
std::set<boost::shared_ptr<Job> >& |
3948 |
20 Jul 20 |
peter |
129 |
prerequisite(const std::unique_lock<std::mutex>& lock); |
3853 |
01 Jan 20 |
peter |
130 |
const std::set<boost::shared_ptr<Job> >& |
3948 |
20 Jul 20 |
peter |
131 |
prerequisite(const std::unique_lock<std::mutex>& lock) const; |
3681 |
22 Aug 17 |
peter |
// - pristine is what it says |
3681 |
22 Aug 17 |
peter |
// - prepared - job has been either submitted directly a job that |
3681 |
22 Aug 17 |
peter |
// depends on job has been submitted et.c. |
3681 |
22 Aug 17 |
peter |
// - running - job has been sent to queue for workers to chew on |
3681 |
22 Aug 17 |
peter |
// - completed - job has returned |
3853 |
01 Jan 20 |
peter |
137 |
enum status_type { pristine, prepared, running, completed}; |
3853 |
01 Jan 20 |
peter |
138 |
status_type status_; |
3948 |
20 Jul 20 |
peter |
139 |
status_type status(const std::unique_lock<std::mutex>& lock) const; |
3948 |
20 Jul 20 |
peter |
140 |
void status(const std::unique_lock<std::mutex>& lock, status_type s); |
3402 |
31 Mar 15 |
peter |
141 |
unsigned priority_; |
3402 |
31 Mar 15 |
peter |
142 |
unsigned id_; |
3405 |
06 Apr 15 |
peter |
143 |
boost::exception_ptr error_; |
3346 |
06 Nov 14 |
peter |
144 |
}; // end class Job |
3346 |
06 Nov 14 |
peter |
145 |
|
3346 |
06 Nov 14 |
peter |
146 |
/** |
3346 |
06 Nov 14 |
peter |
\brief constructor |
3346 |
06 Nov 14 |
peter |
148 |
|
3346 |
06 Nov 14 |
peter |
\param threads number of threads that are used |
3346 |
06 Nov 14 |
peter |
150 |
*/ |
3346 |
06 Nov 14 |
peter |
151 |
Scheduler(unsigned int threads); |
3346 |
06 Nov 14 |
peter |
152 |
|
3346 |
06 Nov 14 |
peter |
153 |
/** |
3401 |
31 Mar 15 |
peter |
\brief add a dependency rule |
3401 |
31 Mar 15 |
peter |
155 |
|
3401 |
31 Mar 15 |
peter |
Add a dependency that Job \a prerequisite has to complete |
3401 |
31 Mar 15 |
peter |
before Job \a job is run. |
3681 |
22 Aug 17 |
peter |
158 |
|
3681 |
22 Aug 17 |
peter |
Note, job cannot have been submitted, neither directly or |
3681 |
22 Aug 17 |
peter |
by being prerequisite of a submitted job. |
3401 |
31 Mar 15 |
peter |
161 |
*/ |
3401 |
31 Mar 15 |
peter |
162 |
void add_dependency(boost::shared_ptr<Job> job, |
3401 |
31 Mar 15 |
peter |
163 |
boost::shared_ptr<Job> prerequisite); |
3405 |
06 Apr 15 |
peter |
164 |
/** |
3405 |
06 Apr 15 |
peter |
\brief interrrupt all jobs |
3405 |
06 Apr 15 |
peter |
166 |
*/ |
3405 |
06 Apr 15 |
peter |
167 |
void interrupt(void); |
3401 |
31 Mar 15 |
peter |
168 |
|
3401 |
31 Mar 15 |
peter |
169 |
/** |
3679 |
18 Aug 17 |
peter |
\return Number of jobs that are either running or queued, i.e., |
3679 |
18 Aug 17 |
peter |
jobs that are waiting for a dependency are not counted. |
3679 |
18 Aug 17 |
peter |
172 |
|
3679 |
18 Aug 17 |
peter |
\since New in yat 0.15 |
3679 |
18 Aug 17 |
peter |
174 |
*/ |
3679 |
18 Aug 17 |
peter |
175 |
size_t jobs(void) const; |
3679 |
18 Aug 17 |
peter |
176 |
|
3679 |
18 Aug 17 |
peter |
177 |
/** |
3348 |
13 Nov 14 |
peter |
\brief submit a \a job to Scheduler |
3349 |
13 Nov 14 |
peter |
179 |
|
3349 |
13 Nov 14 |
peter |
If \a job depends on other jobs, they are also submitted to the |
3349 |
13 Nov 14 |
peter |
Scheduler. |
3346 |
06 Nov 14 |
peter |
182 |
*/ |
3681 |
22 Aug 17 |
peter |
183 |
void submit(const boost::shared_ptr<Job>& job); |
3346 |
06 Nov 14 |
peter |
184 |
|
3346 |
06 Nov 14 |
peter |
185 |
/** |
3826 |
18 Jul 19 |
peter |
\return number of threads used |
3826 |
18 Jul 19 |
peter |
187 |
|
3826 |
18 Jul 19 |
peter |
\since new in yat 0.17 |
3826 |
18 Jul 19 |
peter |
189 |
*/ |
3848 |
23 Sep 19 |
peter |
190 |
unsigned int threads(void) const; |
3826 |
18 Jul 19 |
peter |
191 |
|
3826 |
18 Jul 19 |
peter |
192 |
/** |
3848 |
23 Sep 19 |
peter |
Change number of threads used. If \a n is greater than current |
3848 |
23 Sep 19 |
peter |
number of threads, additional threads are launched. If \a n is |
3848 |
23 Sep 19 |
peter |
smaller than current number used, a number of threads are |
3848 |
23 Sep 19 |
peter |
notified to end after the current job has been completed. A |
3848 |
23 Sep 19 |
peter |
decrease in threads therefore does not have an immediate |
3848 |
23 Sep 19 |
peter |
effect. |
3848 |
23 Sep 19 |
peter |
199 |
|
3848 |
23 Sep 19 |
peter |
\since new in yat 0.17 |
3848 |
23 Sep 19 |
peter |
201 |
*/ |
3848 |
23 Sep 19 |
peter |
202 |
void threads(unsigned int n); |
3848 |
23 Sep 19 |
peter |
203 |
|
3848 |
23 Sep 19 |
peter |
204 |
/** |
3348 |
13 Nov 14 |
peter |
\brief wait for all jobs to finish |
3346 |
06 Nov 14 |
peter |
206 |
*/ |
3348 |
13 Nov 14 |
peter |
207 |
void wait(void); |
3346 |
06 Nov 14 |
peter |
208 |
|
3346 |
06 Nov 14 |
peter |
209 |
private: |
3848 |
23 Sep 19 |
peter |
// forward declaration |
3848 |
23 Sep 19 |
peter |
211 |
class JobHandler; |
3848 |
23 Sep 19 |
peter |
212 |
|
3402 |
31 Mar 15 |
peter |
213 |
typedef boost::shared_ptr<Scheduler::Job> JobPtr; |
3402 |
31 Mar 15 |
peter |
214 |
|
3848 |
23 Sep 19 |
peter |
215 |
class Messenger |
3848 |
23 Sep 19 |
peter |
216 |
{ |
3848 |
23 Sep 19 |
peter |
217 |
public: |
3848 |
23 Sep 19 |
peter |
218 |
virtual void operator()(JobHandler& handler)=0; |
3848 |
23 Sep 19 |
peter |
219 |
}; |
3848 |
23 Sep 19 |
peter |
220 |
|
3848 |
23 Sep 19 |
peter |
221 |
typedef boost::shared_ptr<Messenger> MessengerPtr; |
3848 |
23 Sep 19 |
peter |
222 |
typedef Queue<MessengerPtr> MessengerQueue; |
3848 |
23 Sep 19 |
peter |
223 |
|
3848 |
23 Sep 19 |
peter |
224 |
class JobMessenger : public Messenger |
3848 |
23 Sep 19 |
peter |
225 |
{ |
3848 |
23 Sep 19 |
peter |
226 |
public: |
3848 |
23 Sep 19 |
peter |
227 |
JobMessenger(const JobPtr&); |
3848 |
23 Sep 19 |
peter |
228 |
void operator()(JobHandler& handler); |
3848 |
23 Sep 19 |
peter |
229 |
private: |
3848 |
23 Sep 19 |
peter |
230 |
JobPtr job_; |
3848 |
23 Sep 19 |
peter |
231 |
}; |
3848 |
23 Sep 19 |
peter |
232 |
|
3848 |
23 Sep 19 |
peter |
233 |
|
3848 |
23 Sep 19 |
peter |
234 |
class SchedulerIsWaiting : public Messenger |
3848 |
23 Sep 19 |
peter |
235 |
{ |
3848 |
23 Sep 19 |
peter |
236 |
public: |
3848 |
23 Sep 19 |
peter |
237 |
void operator()(JobHandler& handler); |
3848 |
23 Sep 19 |
peter |
238 |
}; |
3848 |
23 Sep 19 |
peter |
239 |
|
3848 |
23 Sep 19 |
peter |
240 |
|
3848 |
23 Sep 19 |
peter |
241 |
class InterruptWorkers : public Messenger |
3848 |
23 Sep 19 |
peter |
242 |
{ |
3848 |
23 Sep 19 |
peter |
243 |
public: |
3848 |
23 Sep 19 |
peter |
244 |
void operator()(JobHandler& handler); |
3848 |
23 Sep 19 |
peter |
245 |
}; |
3848 |
23 Sep 19 |
peter |
246 |
|
3848 |
23 Sep 19 |
peter |
247 |
|
3848 |
23 Sep 19 |
peter |
// Class used to change number of workers |
3848 |
23 Sep 19 |
peter |
249 |
class WorkForceSizer : public Messenger |
3848 |
23 Sep 19 |
peter |
250 |
{ |
3848 |
23 Sep 19 |
peter |
251 |
public: |
3848 |
23 Sep 19 |
peter |
252 |
void operator()(JobHandler& handler); |
3848 |
23 Sep 19 |
peter |
253 |
}; |
3848 |
23 Sep 19 |
peter |
254 |
|
3848 |
23 Sep 19 |
peter |
255 |
|
3402 |
31 Mar 15 |
peter |
256 |
struct LowerPriority |
3402 |
31 Mar 15 |
peter |
257 |
{ |
3402 |
31 Mar 15 |
peter |
258 |
bool operator()(const JobPtr& lhs, const JobPtr& rhs) const; |
3402 |
31 Mar 15 |
peter |
259 |
}; |
3402 |
31 Mar 15 |
peter |
260 |
|
3402 |
31 Mar 15 |
peter |
// some typedefs for convenience |
3402 |
31 Mar 15 |
peter |
262 |
typedef PriorityQueue<JobPtr, LowerPriority> JobQueue; |
3402 |
31 Mar 15 |
peter |
263 |
|
3346 |
06 Nov 14 |
peter |
// \internal class that does the job |
3346 |
06 Nov 14 |
peter |
265 |
// |
3346 |
06 Nov 14 |
peter |
// It processes any job that is pushed to the \a queue until a |
3346 |
06 Nov 14 |
peter |
// NULL Job shows up which signals that the work is done. When |
3346 |
06 Nov 14 |
peter |
// NULL is observed the NULL Job is pushed to the queue so |
3346 |
06 Nov 14 |
peter |
// co-workers are notified too. |
3346 |
06 Nov 14 |
peter |
270 |
class Worker |
3346 |
06 Nov 14 |
peter |
271 |
{ |
3346 |
06 Nov 14 |
peter |
272 |
public: |
3848 |
23 Sep 19 |
peter |
273 |
Worker(JobQueue& queue, MessengerQueue& completed); |
3346 |
06 Nov 14 |
peter |
274 |
void operator()(void); |
3346 |
06 Nov 14 |
peter |
275 |
private: |
3402 |
31 Mar 15 |
peter |
276 |
JobQueue& queue_; |
3848 |
23 Sep 19 |
peter |
277 |
MessengerQueue& completed_; |
3346 |
06 Nov 14 |
peter |
278 |
}; // end class Worker |
3346 |
06 Nov 14 |
peter |
279 |
|
3823 |
16 Jul 19 |
peter |
280 |
|
3853 |
01 Jan 20 |
peter |
281 |
class Dependency |
3853 |
01 Jan 20 |
peter |
282 |
{ |
3853 |
01 Jan 20 |
peter |
283 |
public: |
3948 |
20 Jul 20 |
peter |
284 |
typedef std::unique_lock<std::mutex> Lock; |
3853 |
01 Jan 20 |
peter |
285 |
|
3853 |
01 Jan 20 |
peter |
286 |
void add(const JobPtr& child, const JobPtr& parent, const Lock& lock); |
3853 |
01 Jan 20 |
peter |
287 |
void remove(const JobPtr& parent, const Lock& lock); |
3853 |
01 Jan 20 |
peter |
288 |
std::vector<JobPtr>& children(const JobPtr& key, const Lock& lock); |
3948 |
20 Jul 20 |
peter |
289 |
std::mutex& mutex(void); |
3853 |
01 Jan 20 |
peter |
290 |
private: |
3948 |
20 Jul 20 |
peter |
291 |
std::mutex mutex_; |
3853 |
01 Jan 20 |
peter |
292 |
|
3853 |
01 Jan 20 |
peter |
// job in key has to finish before jobs in vector |
3853 |
01 Jan 20 |
peter |
294 |
std::map<JobPtr, std::vector<JobPtr> > children_; |
3853 |
01 Jan 20 |
peter |
295 |
|
3853 |
01 Jan 20 |
peter |
296 |
std::vector<JobPtr> empty_vector_; |
3853 |
01 Jan 20 |
peter |
297 |
}; |
3853 |
01 Jan 20 |
peter |
298 |
|
3853 |
01 Jan 20 |
peter |
299 |
|
3823 |
16 Jul 19 |
peter |
300 |
class JobHandlerData |
3823 |
16 Jul 19 |
peter |
301 |
{ |
3823 |
16 Jul 19 |
peter |
302 |
public: |
3823 |
16 Jul 19 |
peter |
/// thread-safe class around int |
3823 |
16 Jul 19 |
peter |
304 |
class Count |
3823 |
16 Jul 19 |
peter |
305 |
{ |
3823 |
16 Jul 19 |
peter |
306 |
public: |
3823 |
16 Jul 19 |
peter |
/// Constructor |
3823 |
16 Jul 19 |
peter |
308 |
explicit Count(int x=0); |
3823 |
16 Jul 19 |
peter |
/// increase value with 1 |
3823 |
16 Jul 19 |
peter |
310 |
void decrement(void); |
3823 |
16 Jul 19 |
peter |
/// return value |
3823 |
16 Jul 19 |
peter |
312 |
int get(void) const; |
3823 |
16 Jul 19 |
peter |
/// decrease value with 1 |
3823 |
16 Jul 19 |
peter |
314 |
void increment(void); |
3823 |
16 Jul 19 |
peter |
/// modify value |
3823 |
16 Jul 19 |
peter |
316 |
void set(int x); |
3823 |
16 Jul 19 |
peter |
317 |
private: |
3948 |
20 Jul 20 |
peter |
318 |
mutable std::mutex mutex_; |
3823 |
16 Jul 19 |
peter |
319 |
int x_; |
3823 |
16 Jul 19 |
peter |
320 |
}; |
3823 |
16 Jul 19 |
peter |
321 |
|
3848 |
23 Sep 19 |
peter |
322 |
JobHandlerData(void); |
3823 |
16 Jul 19 |
peter |
323 |
Queue<boost::exception_ptr>& error(void) const; |
3823 |
16 Jul 19 |
peter |
324 |
|
3853 |
01 Jan 20 |
peter |
325 |
Dependency& dependency(void); |
3853 |
01 Jan 20 |
peter |
326 |
const Dependency& dependency(void) const; |
3853 |
01 Jan 20 |
peter |
327 |
|
3848 |
23 Sep 19 |
peter |
328 |
const MessengerQueue& messengers(void) const; |
3848 |
23 Sep 19 |
peter |
329 |
MessengerQueue& messengers(void); // |
3848 |
23 Sep 19 |
peter |
330 |
const JobQueue& queue(void) const; // |
3823 |
16 Jul 19 |
peter |
331 |
JobQueue& queue(void); |
3823 |
16 Jul 19 |
peter |
332 |
|
3823 |
16 Jul 19 |
peter |
333 |
const Count& running_jobs(void) const; |
3823 |
16 Jul 19 |
peter |
334 |
Count& running_jobs(void); |
3823 |
16 Jul 19 |
peter |
335 |
|
3848 |
23 Sep 19 |
peter |
336 |
const Count& n_threads(void) const; |
3848 |
23 Sep 19 |
peter |
337 |
Count& n_threads(void); |
3823 |
16 Jul 19 |
peter |
338 |
private: |
3823 |
16 Jul 19 |
peter |
339 |
mutable Queue<boost::exception_ptr> error_; |
3848 |
23 Sep 19 |
peter |
340 |
MessengerQueue messengers_; |
3848 |
23 Sep 19 |
peter |
// This is the queue workers are consuming from. |
3823 |
16 Jul 19 |
peter |
342 |
JobQueue queue_; |
3823 |
16 Jul 19 |
peter |
343 |
|
3948 |
20 Jul 20 |
peter |
344 |
std::mutex mutex_; |
3853 |
01 Jan 20 |
peter |
345 |
|
3823 |
16 Jul 19 |
peter |
346 |
Count running_jobs_; |
3823 |
16 Jul 19 |
peter |
347 |
Count threads_; |
3853 |
01 Jan 20 |
peter |
348 |
|
3853 |
01 Jan 20 |
peter |
349 |
Dependency dependency_; |
3823 |
16 Jul 19 |
peter |
350 |
}; |
3823 |
16 Jul 19 |
peter |
351 |
|
3823 |
16 Jul 19 |
peter |
352 |
|
3681 |
22 Aug 17 |
peter |
// \internal Class that handles job |
3681 |
22 Aug 17 |
peter |
354 |
class JobHandler |
3681 |
22 Aug 17 |
peter |
355 |
{ |
3681 |
22 Aug 17 |
peter |
356 |
public: |
3823 |
16 Jul 19 |
peter |
357 |
JobHandler(JobHandlerData& data); |
3681 |
22 Aug 17 |
peter |
358 |
|
3681 |
22 Aug 17 |
peter |
359 |
void operator()(void); |
3848 |
23 Sep 19 |
peter |
360 |
void create_workers(unsigned int n); |
3848 |
23 Sep 19 |
peter |
361 |
JobHandlerData& data(void); |
3848 |
23 Sep 19 |
peter |
362 |
void interrupt_workers(void); |
3848 |
23 Sep 19 |
peter |
363 |
void kill_workers(void); |
3848 |
23 Sep 19 |
peter |
364 |
void kill_workers(unsigned int n); |
3848 |
23 Sep 19 |
peter |
// If \a job has parent jobs, which need to finish first, update |
3848 |
23 Sep 19 |
peter |
// map children_ to reflect that. If all parents have finished, |
3848 |
23 Sep 19 |
peter |
// send job to queue. |
3848 |
23 Sep 19 |
peter |
368 |
void process(JobPtr& job); |
3848 |
23 Sep 19 |
peter |
369 |
void remove_joined_workers(void); |
3848 |
23 Sep 19 |
peter |
370 |
void scheduler_is_waiting(bool value); |
3848 |
23 Sep 19 |
peter |
371 |
unsigned int n_target_workers(void) const; |
3848 |
23 Sep 19 |
peter |
372 |
void wait_workers(void) const; |
3681 |
22 Aug 17 |
peter |
373 |
private: |
3681 |
22 Aug 17 |
peter |
374 |
|
3681 |
22 Aug 17 |
peter |
// If job is ready to be submitted i.e. all prerequisite have |
3681 |
22 Aug 17 |
peter |
// completed, then submit job to queue for workers to chew on. |
3853 |
01 Jan 20 |
peter |
377 |
void prepare(JobPtr job, const Dependency::Lock& lock); |
3681 |
22 Aug 17 |
peter |
// handle jobs returned from worker |
3848 |
23 Sep 19 |
peter |
379 |
// |
3848 |
23 Sep 19 |
peter |
// function called when job has finished and returned from |
3848 |
23 Sep 19 |
peter |
// worker. If there are any jobs that depend on \a job, those jobs |
3848 |
23 Sep 19 |
peter |
// are notified and if it makes them ready to be processed they |
3848 |
23 Sep 19 |
peter |
// are sent to queue. |
3853 |
01 Jan 20 |
peter |
384 |
void post_process(JobPtr job, const Dependency::Lock& lock); |
3681 |
22 Aug 17 |
peter |
385 |
|
3853 |
01 Jan 20 |
peter |
386 |
void send2queue(JobPtr& job, |
3948 |
20 Jul 20 |
peter |
387 |
const std::unique_lock<std::mutex>& lock); |
3823 |
16 Jul 19 |
peter |
388 |
|
3823 |
16 Jul 19 |
peter |
389 |
JobHandlerData* data_; |
3848 |
23 Sep 19 |
peter |
390 |
bool scheduler_is_waiting_; |
3848 |
23 Sep 19 |
peter |
391 |
unsigned int job_count_; |
3848 |
23 Sep 19 |
peter |
392 |
void join_workers(void); |
3681 |
22 Aug 17 |
peter |
393 |
|
3948 |
20 Jul 20 |
peter |
394 |
typedef std::list<boost::shared_ptr<std::thread> > WorkerList; |
3918 |
31 May 20 |
peter |
// We keep workers here (rather than in JobHandler::operator() |
3918 |
31 May 20 |
peter |
// scope), so we can access it from other functions and don't |
3918 |
31 May 20 |
peter |
// need to pass it around. |
3848 |
23 Sep 19 |
peter |
398 |
WorkerList workers_; |
3848 |
23 Sep 19 |
peter |
// Number of Workers minus number of poison pills sent for them |
3848 |
23 Sep 19 |
peter |
400 |
unsigned int n_target_workers_; |
3848 |
23 Sep 19 |
peter |
401 |
}; // end class JobHandler |
3681 |
22 Aug 17 |
peter |
402 |
|
3681 |
22 Aug 17 |
peter |
// If an error has been detected (and stored in error_), rethrow it. |
3694 |
23 Sep 17 |
peter |
404 |
void throw_if_error(void) const; |
3346 |
06 Nov 14 |
peter |
405 |
|
3948 |
20 Jul 20 |
peter |
406 |
mutable std::mutex mutex_; |
3823 |
16 Jul 19 |
peter |
407 |
JobHandlerData data_; |
3948 |
20 Jul 20 |
peter |
408 |
std::thread job_handler_; |
3346 |
06 Nov 14 |
peter |
409 |
}; // end class Scheduler |
3346 |
06 Nov 14 |
peter |
410 |
|
3346 |
06 Nov 14 |
peter |
411 |
}}} |
3346 |
06 Nov 14 |
peter |
412 |
#endif |