OpenShot Library | OpenShotAudio  0.2.2
juce_ThreadPool.h
1 
2 /** @weakgroup juce_core-threads
3  * @{
4  */
5 /*
6  ==============================================================================
7 
8  This file is part of the JUCE library.
9  Copyright (c) 2017 - ROLI Ltd.
10 
11  JUCE is an open source library subject to commercial or open-source
12  licensing.
13 
14  The code included in this file is provided under the terms of the ISC license
15  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16  To use, copy, modify, and/or distribute this software for any purpose with or
17  without fee is hereby granted provided that the above copyright notice and
18  this permission notice appear in all copies.
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 namespace juce
28 {
29 
30 class ThreadPool;
31 
32 //==============================================================================
33 /**
34  A task that is executed by a ThreadPool object.
35 
36  A ThreadPool keeps a list of ThreadPoolJob objects which are executed by
37  its threads.
38 
39  The runJob() method needs to be implemented to do the task, and if the code that
40  does the work takes a significant time to run, it must keep checking the shouldExit()
41  method to see if something is trying to interrupt the job. If shouldExit() returns
42  true, the runJob() method must return immediately.
43 
44  @see ThreadPool, Thread
45 
46  @tags{Core}
47 */
49 {
50 public:
51  //==============================================================================
52  /** Creates a thread pool job object.
53  After creating your job, add it to a thread pool with ThreadPool::addJob().
54  */
55  explicit ThreadPoolJob (const String& name);
56 
57  /** Destructor. */
58  virtual ~ThreadPoolJob();
59 
60  //==============================================================================
61  /** Returns the name of this job.
62  @see setJobName
63  */
64  String getJobName() const;
65 
66  /** Changes the job's name.
67  @see getJobName
68  */
69  void setJobName (const String& newName);
70 
71  //==============================================================================
72  /** These are the values that can be returned by the runJob() method.
73  */
74  enum JobStatus
75  {
76  jobHasFinished = 0, /**< indicates that the job has finished and can be
77  removed from the pool. */
78 
79  jobNeedsRunningAgain /**< indicates that the job would like to be called
80  again when a thread is free. */
81  };
82 
83  /** Performs the actual work that this job needs to do.
84 
85  Your subclass must implement this method, in which is does its work.
86 
87  If the code in this method takes a significant time to run, it must repeatedly check
88  the shouldExit() method to see if something is trying to interrupt the job.
89  If shouldExit() ever returns true, the runJob() method must return immediately.
90 
91  If this method returns jobHasFinished, then the job will be removed from the pool
92  immediately. If it returns jobNeedsRunningAgain, then the job will be left in the
93  pool and will get a chance to run again as soon as a thread is free.
94 
95  @see shouldExit()
96  */
97  virtual JobStatus runJob() = 0;
98 
99 
100  //==============================================================================
101  /** Returns true if this job is currently running its runJob() method. */
102  bool isRunning() const noexcept { return isActive; }
103 
104  /** Returns true if something is trying to interrupt this job and make it stop.
105 
106  Your runJob() method must call this whenever it gets a chance, and if it ever
107  returns true, the runJob() method must return immediately.
108 
109  @see signalJobShouldExit()
110  */
111  bool shouldExit() const noexcept { return shouldStop; }
112 
113  /** Calling this will cause the shouldExit() method to return true, and the job
114  should (if it's been implemented correctly) stop as soon as possible.
115 
116  @see shouldExit()
117  */
118  void signalJobShouldExit();
119 
120  /** Add a listener to this thread job which will receive a callback when
121  signalJobShouldExit was called on this thread job.
122 
123  @see signalJobShouldExit, removeListener
124  */
125  void addListener (Thread::Listener*);
126 
127  /** Removes a listener added with addListener. */
128  void removeListener (Thread::Listener*);
129 
130  //==============================================================================
131  /** If the calling thread is being invoked inside a runJob() method, this will
132  return the ThreadPoolJob that it belongs to.
133  */
134  static ThreadPoolJob* getCurrentThreadPoolJob();
135 
136  //==============================================================================
137 private:
138  friend class ThreadPool;
139  String jobName;
140  ThreadPool* pool = nullptr;
141  std::atomic<bool> shouldStop { false }, isActive { false }, shouldBeDeleted { false };
143 
144  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolJob)
145 };
146 
147 
148 //==============================================================================
149 /**
150  A set of threads that will run a list of jobs.
151 
152  When a ThreadPoolJob object is added to the ThreadPool's list, its runJob() method
153  will be called by the next pooled thread that becomes free.
154 
155  @see ThreadPoolJob, Thread
156 
157  @tags{Core}
158 */
160 {
161 public:
162  //==============================================================================
163  /** Creates a thread pool.
164  Once you've created a pool, you can give it some jobs by calling addJob().
165 
166  @param numberOfThreads the number of threads to run. These will be started
167  immediately, and will run until the pool is deleted.
168  @param threadStackSize the size of the stack of each thread. If this value
169  is zero then the default stack size of the OS will
170  be used.
171  */
172  ThreadPool (int numberOfThreads, size_t threadStackSize = 0);
173 
174  /** Creates a thread pool with one thread per CPU core.
175  Once you've created a pool, you can give it some jobs by calling addJob().
176  If you want to specify the number of threads, use the other constructor; this
177  one creates a pool which has one thread for each CPU core.
178  @see SystemStats::getNumCpus()
179  */
180  ThreadPool();
181 
182  /** Destructor.
183 
184  This will attempt to remove all the jobs before deleting, but if you want to
185  specify a timeout, you should call removeAllJobs() explicitly before deleting
186  the pool.
187  */
188  ~ThreadPool();
189 
190  //==============================================================================
191  /** A callback class used when you need to select which ThreadPoolJob objects are suitable
192  for some kind of operation.
193  @see ThreadPool::removeAllJobs
194  */
196  {
197  public:
198  virtual ~JobSelector() = default;
199 
200  /** Should return true if the specified thread matches your criteria for whatever
201  operation that this object is being used for.
202 
203  Any implementation of this method must be extremely fast and thread-safe!
204  */
205  virtual bool isJobSuitable (ThreadPoolJob* job) = 0;
206  };
207 
208  //==============================================================================
209  /** Adds a job to the queue.
210 
211  Once a job has been added, then the next time a thread is free, it will run
212  the job's ThreadPoolJob::runJob() method. Depending on the return value of the
213  runJob() method, the pool will either remove the job from the pool or add it to
214  the back of the queue to be run again.
215 
216  If deleteJobWhenFinished is true, then the job object will be owned and deleted by
217  the pool when not needed - if you do this, make sure that your object's destructor
218  is thread-safe.
219 
220  If deleteJobWhenFinished is false, the pointer will be used but not deleted, and
221  the caller is responsible for making sure the object is not deleted before it has
222  been removed from the pool.
223  */
224  void addJob (ThreadPoolJob* job,
225  bool deleteJobWhenFinished);
226 
227  /** Adds a lambda function to be called as a job.
228  This will create an internal ThreadPoolJob object to encapsulate and call the lambda.
229  */
230  void addJob (std::function<ThreadPoolJob::JobStatus()> job);
231 
232  /** Adds a lambda function to be called as a job.
233  This will create an internal ThreadPoolJob object to encapsulate and call the lambda.
234  */
235  void addJob (std::function<void()> job);
236 
237  /** Tries to remove a job from the pool.
238 
239  If the job isn't yet running, this will simply remove it. If it is running, it
240  will wait for it to finish.
241 
242  If the timeout period expires before the job finishes running, then the job will be
243  left in the pool and this will return false. It returns true if the job is successfully
244  stopped and removed.
245 
246  @param job the job to remove
247  @param interruptIfRunning if true, then if the job is currently busy, its
248  ThreadPoolJob::signalJobShouldExit() method will be called to try
249  to interrupt it. If false, then if the job will be allowed to run
250  until it stops normally (or the timeout expires)
251  @param timeOutMilliseconds the length of time this method should wait for the job to finish
252  before giving up and returning false
253  */
254  bool removeJob (ThreadPoolJob* job,
255  bool interruptIfRunning,
256  int timeOutMilliseconds);
257 
258  /** Tries to remove all jobs from the pool.
259 
260  @param interruptRunningJobs if true, then all running jobs will have their ThreadPoolJob::signalJobShouldExit()
261  methods called to try to interrupt them
262  @param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
263  before giving up and returning false
264  @param selectedJobsToRemove if this is not a nullptr, the JobSelector object is asked to decide
265  which jobs should be removed. If it is a nullptr, all jobs are removed
266  @returns true if all jobs are successfully stopped and removed; false if the timeout period
267  expires while waiting for one or more jobs to stop
268  */
269  bool removeAllJobs (bool interruptRunningJobs,
270  int timeOutMilliseconds,
271  JobSelector* selectedJobsToRemove = nullptr);
272 
273  /** Returns the number of jobs currently running or queued. */
274  int getNumJobs() const noexcept;
275 
276  /** Returns the number of threads assigned to this thread pool. */
277  int getNumThreads() const noexcept;
278 
279  /** Returns one of the jobs in the queue.
280 
281  Note that this can be a very volatile list as jobs might be continuously getting shifted
282  around in the list, and this method may return nullptr if the index is currently out-of-range.
283  */
284  ThreadPoolJob* getJob (int index) const noexcept;
285 
286  /** Returns true if the given job is currently queued or running.
287 
288  @see isJobRunning()
289  */
290  bool contains (const ThreadPoolJob* job) const noexcept;
291 
292  /** Returns true if the given job is currently being run by a thread. */
293  bool isJobRunning (const ThreadPoolJob* job) const noexcept;
294 
295  /** Waits until a job has finished running and has been removed from the pool.
296 
297  This will wait until the job is no longer in the pool - i.e. until its
298  runJob() method returns ThreadPoolJob::jobHasFinished.
299 
300  If the timeout period expires before the job finishes, this will return false;
301  it returns true if the job has finished successfully.
302  */
303  bool waitForJobToFinish (const ThreadPoolJob* job,
304  int timeOutMilliseconds) const;
305 
306  /** If the given job is in the queue, this will move it to the front so that it
307  is the next one to be executed.
308  */
309  void moveJobToFront (const ThreadPoolJob* jobToMove) noexcept;
310 
311  /** Returns a list of the names of all the jobs currently running or queued.
312  If onlyReturnActiveJobs is true, only the ones currently running are returned.
313  */
314  StringArray getNamesOfAllJobs (bool onlyReturnActiveJobs) const;
315 
316  /** Changes the priority of all the threads.
317  This will call Thread::setPriority() for each thread in the pool.
318  May return false if for some reason the priority can't be changed.
319  */
320  bool setThreadPriorities (int newPriority);
321 
322 
323 private:
324  //==============================================================================
326 
327  struct ThreadPoolThread;
328  friend class ThreadPoolJob;
330 
331  CriticalSection lock;
332  WaitableEvent jobFinishedSignal;
333 
334  bool runNextJob (ThreadPoolThread&);
335  ThreadPoolJob* pickNextJobToRun();
336  void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;
337  void createThreads (int numThreads, size_t threadStackSize = 0);
338  void stopThreads();
339 
340  // Note that this method has changed, and no longer has a parameter to indicate
341  // whether the jobs should be deleted - see the new method for details.
342  void removeAllJobs (bool, int, bool);
343 
344  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPool)
345 };
346 
347 } // namespace juce
348 
349 /** @}*/
#define JUCE_API
This macro is added to all JUCE public class declarations.
A callback class used when you need to select which ThreadPoolJob objects are suitable for some kind ...
Allows threads to wait for events triggered by other threads.
A special array for holding a list of strings.
The JUCE String class!
Definition: juce_String.h:42
Holds a set of objects and can invoke a member function callback on each object in the set with a sin...
JobStatus
These are the values that can be returned by the runJob() method.
Used to receive callbacks for thread exit calls.
Definition: juce_Thread.h:184
bool isRunning() const noexcept
Returns true if this job is currently running its runJob() method.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
A re-entrant mutex.
An array designed for holding objects.
A task that is executed by a ThreadPool object.
A set of threads that will run a list of jobs.
bool shouldExit() const noexcept
Returns true if something is trying to interrupt this job and make it stop.