The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #ifndef __JUCE_THREADPOOL_JUCEHEADER__
  24. #define __JUCE_THREADPOOL_JUCEHEADER__
  25. #include "juce_Thread.h"
  26. #include "juce_ScopedLock.h"
  27. #include "../text/juce_StringArray.h"
  28. #include "../containers/juce_VoidArray.h"
  29. class ThreadPool;
  30. class ThreadPoolThread;
  31. //==============================================================================
  32. /**
  33. A task that is executed by a ThreadPool object.
  34. A ThreadPool keeps a list of ThreadPoolJob objects which are executed by
  35. its threads.
  36. The runJob() method needs to be implemented to do the task, and if the code that
  37. does the work takes a significant time to run, it must keep checking the shouldExit()
  38. method to see if something is trying to interrupt the job. If shouldExit() returns
  39. true, the runJob() method must return immediately.
  40. @see ThreadPool, Thread
  41. */
  42. class JUCE_API ThreadPoolJob
  43. {
  44. public:
  45. //==============================================================================
  46. /** Creates a thread pool job object.
  47. After creating your job, add it to a thread pool with ThreadPool::addJob().
  48. */
  49. ThreadPoolJob (const String& name);
  50. /** Destructor. */
  51. virtual ~ThreadPoolJob();
  52. //==============================================================================
  53. /** Returns the name of this job.
  54. @see setJobName
  55. */
  56. const String getJobName() const;
  57. /** Changes the job's name.
  58. @see getJobName
  59. */
  60. void setJobName (const String& newName);
  61. //==============================================================================
  62. /** These are the values that can be returned by the runJob() method.
  63. */
  64. enum JobStatus
  65. {
  66. jobHasFinished = 0, /**< indicates that the job has finished and can be
  67. removed from the pool. */
  68. jobHasFinishedAndShouldBeDeleted, /**< indicates that the job has finished and that it
  69. should be automatically deleted by the pool. */
  70. jobNeedsRunningAgain /**< indicates that the job would like to be called
  71. again when a thread is free. */
  72. };
  73. /** Peforms the actual work that this job needs to do.
  74. Your subclass must implement this method, in which is does its work.
  75. If the code in this method takes a significant time to run, it must repeatedly check
  76. the shouldExit() method to see if something is trying to interrupt the job.
  77. If shouldExit() ever returns true, the runJob() method must return immediately.
  78. If this method returns jobHasFinished, then the job will be removed from the pool
  79. immediately. If it returns jobNeedsRunningAgain, then the job will be left in the
  80. pool and will get a chance to run again as soon as a thread is free.
  81. @see shouldExit()
  82. */
  83. virtual JobStatus runJob() = 0;
  84. //==============================================================================
  85. /** Returns true if this job is currently running its runJob() method. */
  86. bool isRunning() const throw() { return isActive; }
  87. /** Returns true if something is trying to interrupt this job and make it stop.
  88. Your runJob() method must call this whenever it gets a chance, and if it ever
  89. returns true, the runJob() method must return immediately.
  90. @see signalJobShouldExit()
  91. */
  92. bool shouldExit() const throw() { return shouldStop; }
  93. /** Calling this will cause the shouldExit() method to return true, and the job
  94. should (if it's been implemented correctly) stop as soon as possible.
  95. @see shouldExit()
  96. */
  97. void signalJobShouldExit();
  98. //==============================================================================
  99. juce_UseDebuggingNewOperator
  100. private:
  101. friend class ThreadPool;
  102. friend class ThreadPoolThread;
  103. String jobName;
  104. ThreadPool* pool;
  105. bool shouldStop, isActive, shouldBeDeleted;
  106. };
  107. //==============================================================================
  108. /**
  109. A set of threads that will run a list of jobs.
  110. When a ThreadPoolJob object is added to the ThreadPool's list, its run() method
  111. will be called by the next pooled thread that becomes free.
  112. @see ThreadPoolJob, Thread
  113. */
  114. class JUCE_API ThreadPool
  115. {
  116. public:
  117. //==============================================================================
  118. /** Creates a thread pool.
  119. Once you've created a pool, you can give it some things to do with the addJob()
  120. method.
  121. @param numberOfThreads the maximum number of actual threads to run.
  122. @param startThreadsOnlyWhenNeeded if this is true, then no threads will be started
  123. until there are some jobs to run. If false, then
  124. all the threads will be fired-up immediately so that
  125. they're ready for action
  126. @param stopThreadsWhenNotUsedTimeoutMs if this timeout is > 0, then if any threads have been
  127. inactive for this length of time, they will automatically
  128. be stopped until more jobs come along and they're needed
  129. */
  130. ThreadPool (const int numberOfThreads,
  131. const bool startThreadsOnlyWhenNeeded = true,
  132. const int stopThreadsWhenNotUsedTimeoutMs = 5000);
  133. /** Destructor.
  134. This will attempt to remove all the jobs before deleting, but if you want to
  135. specify a timeout, you should call removeAllJobs() explicitly before deleting
  136. the pool.
  137. */
  138. ~ThreadPool();
  139. //==============================================================================
  140. /** Adds a job to the queue.
  141. Once a job has been added, then the next time a thread is free, it will run
  142. the job's ThreadPoolJob::runJob() method. Depending on the return value of the
  143. runJob() method, the pool will either remove the job from the pool or add it to
  144. the back of the queue to be run again.
  145. */
  146. void addJob (ThreadPoolJob* const job);
  147. /** Tries to remove a job from the pool.
  148. If the job isn't yet running, this will simply remove it. If it is running, it
  149. will wait for it to finish.
  150. If the timeout period expires before the job finishes running, then the job will be
  151. left in the pool and this will return false. It returns true if the job is sucessfully
  152. stopped and removed.
  153. @param job the job to remove
  154. @param interruptIfRunning if true, then if the job is currently busy, its
  155. ThreadPoolJob::signalJobShouldExit() method will be called to try
  156. to interrupt it. If false, then if the job will be allowed to run
  157. until it stops normally (or the timeout expires)
  158. @param timeOutMilliseconds the length of time this method should wait for the job to finish
  159. before giving up and returning false
  160. */
  161. bool removeJob (ThreadPoolJob* const job,
  162. const bool interruptIfRunning,
  163. const int timeOutMilliseconds);
  164. /** Tries clear all jobs from the pool.
  165. @param interruptRunningJobs if true, then all running jobs will have their ThreadPoolJob::signalJobShouldExit()
  166. methods called to try to interrupt them
  167. @param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
  168. before giving up and returning false
  169. @returns true if all jobs are successfully stopped and removed; false if the timeout period
  170. expires while waiting for them to stop
  171. */
  172. bool removeAllJobs (const bool interruptRunningJobs,
  173. const int timeOutMilliseconds);
  174. /** Returns the number of jobs currently running or queued.
  175. */
  176. int getNumJobs() const throw();
  177. /** Returns one of the jobs in the queue.
  178. Note that this can be a very volatile list as jobs might be continuously getting shifted
  179. around in the list, and this method may return 0 if the index is currently out-of-range.
  180. */
  181. ThreadPoolJob* getJob (const int index) const;
  182. /** Returns true if the given job is currently queued or running.
  183. @see isJobRunning()
  184. */
  185. bool contains (const ThreadPoolJob* const job) const throw();
  186. /** Returns true if the given job is currently being run by a thread.
  187. */
  188. bool isJobRunning (const ThreadPoolJob* const job) const;
  189. /** Waits until a job has finished running and has been removed from the pool.
  190. This will wait until the job is no longer in the pool - i.e. until its
  191. runJob() method returns ThreadPoolJob::jobHasFinished.
  192. If the timeout period expires before the job finishes, this will return false;
  193. it returns true if the job has finished successfully.
  194. */
  195. bool waitForJobToFinish (const ThreadPoolJob* const job,
  196. const int timeOutMilliseconds) const;
  197. /** Returns a list of the names of all the jobs currently running or queued.
  198. If onlyReturnActiveJobs is true, only the ones currently running are returned.
  199. */
  200. const StringArray getNamesOfAllJobs (const bool onlyReturnActiveJobs) const;
  201. /** Changes the priority of all the threads.
  202. This will call Thread::setPriority() for each thread in the pool.
  203. */
  204. void setThreadPriorities (const int newPriority);
  205. //==============================================================================
  206. juce_UseDebuggingNewOperator
  207. private:
  208. const int numThreads, threadStopTimeout;
  209. int priority;
  210. Thread** threads;
  211. VoidArray jobs;
  212. CriticalSection lock;
  213. uint32 lastJobEndTime;
  214. friend class ThreadPoolThread;
  215. bool runNextJob();
  216. ThreadPool (const ThreadPool&);
  217. const ThreadPool& operator= (const ThreadPool&);
  218. };
  219. #endif // __JUCE_THREADPOOL_JUCEHEADER__