HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IlmThreadPool.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Contributors to the OpenEXR Project.
4 //
5 
6 #ifndef INCLUDED_ILM_THREAD_POOL_H
7 #define INCLUDED_ILM_THREAD_POOL_H
8 
9 
10 //-----------------------------------------------------------------------------
11 //
12 // class Task, class ThreadPool, class TaskGroup
13 //
14 // Class ThreadPool manages a set of worker threads and accepts
15 // tasks for processing. Tasks added to the thread pool are
16 // executed concurrently by the worker threads.
17 //
18 // Class Task provides an abstract interface for a task which
19 // a ThreadPool works on. Derived classes need to implement the
20 // execute() function which performs the actual task.
21 //
22 // Class TaskGroup allows synchronization on the completion of a set
23 // of tasks. Every task that is added to a ThreadPool belongs to a
24 // single TaskGroup. The destructor of the TaskGroup waits for all
25 // tasks in the group to finish.
26 //
27 // Note: if you plan to use the ThreadPool interface in your own
28 // applications note that the implementation of the ThreadPool calls
29 // operator delete on tasks as they complete. If you define a custom
30 // operator new for your tasks, for instance to use a custom heap,
31 // then you must also write an appropriate operator delete.
32 //
33 //-----------------------------------------------------------------------------
34 
35 #include "IlmThreadNamespace.h"
36 #include "IlmThreadExport.h"
37 #include "IlmThreadConfig.h"
38 
40 
41 class TaskGroup;
42 class Task;
43 
44 //-------------------------------------------------------
45 // ThreadPoolProvider -- this is a pure virtual interface
46 // enabling custom overloading of the threads used and how
47 // the implementation of the processing of tasks
48 // is implemented
49 //-------------------------------------------------------
51 {
52  public:
54  ILMTHREAD_EXPORT virtual ~ThreadPoolProvider();
55 
56  // as in ThreadPool below
57  virtual int numThreads () const = 0;
58  // as in ThreadPool below
59  virtual void setNumThreads (int count) = 0;
60  // as in ThreadPool below
61  virtual void addTask (Task* task) = 0;
62 
63  // Ensure that all tasks in this set are finished
64  // and threads shutdown
65  virtual void finish () = 0;
66 
67  // Make the provider non-copyable
68  ThreadPoolProvider (const ThreadPoolProvider &) = delete;
69  ThreadPoolProvider &operator= (const ThreadPoolProvider &) = delete;
70  ThreadPoolProvider (ThreadPoolProvider &&) = delete;
71  ThreadPoolProvider &operator= (ThreadPoolProvider &&) = delete;
72 };
73 
75 {
76  public:
77  //-------------------------------------------------------
78  // static routine to query how many processors should be
79  // used for processing exr files. The user of ThreadPool
80  // is free to use std::thread::hardware_concurrency or
81  // whatever number of threads is appropriate based on the
82  // application. However, this routine exists such that
83  // in the future, if core counts expand faster than
84  // memory bandwidth, or higher order NUMA machines are built
85  // that we can query, this routine gives a place where we
86  // can centralize that logic
87  //-------------------------------------------------------
89  static unsigned estimateThreadCountForFileIO ();
90 
91  //-------------------------------------------------------
92  // Constructor -- creates numThreads worker threads which
93  // wait until a task is available,
94  // using a default ThreadPoolProvider
95  //-------------------------------------------------------
96 
97  ILMTHREAD_EXPORT ThreadPool (unsigned numThreads = 0);
98 
99 
100  //-----------------------------------------------------------
101  // Destructor -- waits for all tasks to complete, joins all
102  // the threads to the calling thread, and then destroys them.
103  //-----------------------------------------------------------
104 
105  ILMTHREAD_EXPORT virtual ~ThreadPool ();
106  ThreadPool (const ThreadPool&) = delete;
107  ThreadPool& operator= (const ThreadPool&) = delete;
108  ThreadPool (ThreadPool&&) = delete;
109  ThreadPool& operator= (ThreadPool&&) = delete;
110 
111  //--------------------------------------------------------
112  // Query and set the number of worker threads in the pool.
113  //
114  // Warning: never call setNumThreads from within a worker
115  // thread as this will almost certainly cause a deadlock
116  // or crash.
117  //--------------------------------------------------------
118 
119  ILMTHREAD_EXPORT int numThreads () const;
120  ILMTHREAD_EXPORT void setNumThreads (int count);
121 
122  //--------------------------------------------------------
123  // Set the thread provider for the pool.
124  //
125  // The ThreadPool takes ownership of the ThreadPoolProvider
126  // and will call delete on it when it is finished or when
127  // it is changed
128  //
129  // Warning: never call setThreadProvider from within a worker
130  // thread as this will almost certainly cause a deadlock
131  // or crash.
132  //--------------------------------------------------------
133  ILMTHREAD_EXPORT void setThreadProvider (ThreadPoolProvider *provider);
134 
135  //------------------------------------------------------------
136  // Add a task for processing. The ThreadPool can handle any
137  // number of tasks regardless of the number of worker threads.
138  // The tasks are first added onto a queue, and are executed
139  // by threads as they become available, in FIFO order.
140  //------------------------------------------------------------
141 
142  ILMTHREAD_EXPORT void addTask (Task* task);
143 
144 
145  //-------------------------------------------
146  // Access functions for the global threadpool
147  //-------------------------------------------
148 
149  ILMTHREAD_EXPORT static ThreadPool& globalThreadPool ();
150  ILMTHREAD_EXPORT static void addGlobalTask (Task* task);
151 
152  struct ILMTHREAD_HIDDEN Data;
153 
154  protected:
155 
156  Data * _data;
157 };
158 
159 
161 {
162  public:
163 
165  ILMTHREAD_EXPORT virtual ~Task ();
166  Task (const Task&) = delete;
167  Task &operator= (const Task&) = delete;
168  Task (Task&&) = delete;
169  Task& operator= (Task&&) = delete;
170 
171  virtual void execute () = 0;
173  TaskGroup * group();
174 
175  protected:
176 
178 };
179 
180 
182 {
183  public:
184 
186  ILMTHREAD_EXPORT ~TaskGroup();
187 
188  TaskGroup (const TaskGroup& other) = delete;
189  TaskGroup& operator = (const TaskGroup& other) = delete;
190  TaskGroup (TaskGroup&& other) = delete;
191  TaskGroup& operator = (TaskGroup&& other) = delete;
192 
193  // marks one task as finished
194  // should be used by the thread pool provider to notify
195  // as it finishes tasks
196  ILMTHREAD_EXPORT void finishOneTask ();
197 
198  struct ILMTHREAD_HIDDEN Data;
199  Data* const _data;
200 };
201 
202 
204 
205 #endif // INCLUDED_ILM_THREAD_POOL_H
#define ILMTHREAD_EXPORT
Data * _data
GLboolean GLboolean g
Definition: glcorearb.h:1222
#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_ENTER
#define ILMTHREAD_INTERNAL_NAMESPACE_HEADER_EXIT
#define ILMTHREAD_EXPORT_TYPE
TaskGroup * _group
#define ILMTHREAD_HIDDEN
Data *const _data
GLint GLsizei count
Definition: glcorearb.h:405