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