PBRT
|
00001 00002 // 00003 // Copyright (c) 2005, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 #ifndef INCLUDED_ILM_THREAD_POOL_H 00036 #define INCLUDED_ILM_THREAD_POOL_H 00037 00038 //----------------------------------------------------------------------------- 00039 // 00040 // class Task, class ThreadPool, class TaskGroup 00041 // 00042 // Class ThreadPool manages a set of worker threads and accepts 00043 // tasks for processing. Tasks added to the thread pool are 00044 // executed concurrently by the worker threads. 00045 // 00046 // Class Thread provides an abstract interface for a task which 00047 // a ThreadPool works on. Derived classes need to implement the 00048 // execute() function which performs the actual task. 00049 // 00050 // Class TaskTroup allows synchronization on the completion of a set 00051 // of tasks. Every task that is added to a ThreadPool belongs to a 00052 // single TaskGroup. The destructor of the TaskGroup waits for all 00053 // tasks in the group to finish. 00054 // 00055 // Note: if you plan to use the ThreadPool interface in your own 00056 // applications note that the implementation of the ThreadPool calls 00057 // operator delete on tasks as they complete. If you define a custom 00058 // operator new for your tasks, for instance to use a custom heap, 00059 // then you must also write an appropriate operator delete. 00060 // 00061 //----------------------------------------------------------------------------- 00062 00063 namespace IlmThread { 00064 00065 class TaskGroup; 00066 class Task; 00067 00068 00069 class ThreadPool 00070 { 00071 public: 00072 00073 //------------------------------------------------------- 00074 // Constructor -- creates numThreads worker threads which 00075 // wait until a task is available. 00076 //------------------------------------------------------- 00077 00078 ThreadPool (unsigned numThreads = 0); 00079 00080 00081 //----------------------------------------------------------- 00082 // Destructor -- waits for all tasks to complete, joins all 00083 // the threads to the calling thread, and then destroys them. 00084 //----------------------------------------------------------- 00085 00086 virtual ~ThreadPool (); 00087 00088 00089 //-------------------------------------------------------- 00090 // Query and set the number of worker threads in the pool. 00091 // 00092 // Warning: never call setNumThreads from within a worker 00093 // thread as this will almost certainly cause a deadlock 00094 // or crash. 00095 //-------------------------------------------------------- 00096 00097 int numThreads () const; 00098 void setNumThreads (int count); 00099 00100 00101 //------------------------------------------------------------ 00102 // Add a task for processing. The ThreadPool can handle any 00103 // number of tasks regardless of the number of worker threads. 00104 // The tasks are first added onto a queue, and are executed 00105 // by threads as they become available, in FIFO order. 00106 //------------------------------------------------------------ 00107 00108 void addTask (Task* task); 00109 00110 00111 //------------------------------------------- 00112 // Access functions for the global threadpool 00113 //------------------------------------------- 00114 00115 static ThreadPool& globalThreadPool (); 00116 static void addGlobalTask (Task* task); 00117 00118 struct Data; 00119 00120 protected: 00121 00122 Data * _data; 00123 }; 00124 00125 00126 class Task 00127 { 00128 public: 00129 00130 Task (TaskGroup* g); 00131 virtual ~Task (); 00132 00133 virtual void execute () = 0; 00134 TaskGroup * group(); 00135 00136 protected: 00137 00138 TaskGroup * _group; 00139 }; 00140 00141 00142 class TaskGroup 00143 { 00144 public: 00145 00146 TaskGroup(); 00147 ~TaskGroup(); 00148 00149 struct Data; 00150 Data* const _data; 00151 }; 00152 00153 00154 } // namespace IlmThread 00155 00156 #endif