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_H 00036 #define INCLUDED_ILM_THREAD_H 00037 00038 //----------------------------------------------------------------------------- 00039 // 00040 // class Thread 00041 // 00042 // Class Thread is a portable interface to a system-dependent thread 00043 // primitive. In order to make a thread actually do something useful, 00044 // you must derive a subclass from class Thread and implement the 00045 // run() function. If the operating system supports threading then 00046 // the run() function will be executed int a new thread. 00047 // 00048 // The actual creation of the thread is done by the start() routine 00049 // which then calls the run() function. In general the start() 00050 // routine should be called from the constructor of the derived class. 00051 // 00052 // The base-class thread destructor will join/destroy the thread. 00053 // 00054 // IMPORTANT: Due to the mechanisms that encapsulate the low-level 00055 // threading primitives in a C++ class there is a race condition 00056 // with code resembling the following: 00057 // 00058 // { 00059 // WorkerThread myThread; 00060 // } // myThread goes out of scope, is destroyed 00061 // // and the thread is joined 00062 // 00063 // The race is between the parent thread joining the child thread 00064 // in the destructor of myThread, and the run() function in the 00065 // child thread. If the destructor gets executed first then run() 00066 // will be called with an invalid "this" pointer. 00067 // 00068 // This issue can be fixed by using a Semaphore to keep track of 00069 // whether the run() function has already been called. You can 00070 // include a Semaphore member variable within your derived class 00071 // which you post() on in the run() function, and wait() on in the 00072 // destructor before the thread is joined. Alternatively you could 00073 // do something like this: 00074 // 00075 // Semaphore runStarted; 00076 // 00077 // void WorkerThread::run () 00078 // { 00079 // runStarted.post() 00080 // // do some work 00081 // ... 00082 // } 00083 // 00084 // { 00085 // WorkerThread myThread; 00086 // runStarted.wait (); // ensure that we have started 00087 // // the run function 00088 // } // myThread goes out of scope, is destroyed 00089 // // and the thread is joined 00090 // 00091 //----------------------------------------------------------------------------- 00092 00093 #include "IlmBaseConfig.h" 00094 00095 #if defined _WIN32 || defined _WIN64 00096 #ifdef NOMINMAX 00097 #undef NOMINMAX 00098 #endif 00099 #define NOMINMAX 00100 #include <windows.h> 00101 #include <process.h> 00102 #elif HAVE_PTHREAD 00103 #include <pthread.h> 00104 #endif 00105 00106 #if defined(OPENEXR_DLL) && !defined(ZENO_STATIC) 00107 #ifdef ILMTHREAD_EXPORTS 00108 #define ILMTHREAD_EXPORT __declspec(dllexport) 00109 #else 00110 #define ILMTHREAD_EXPORT __declspec(dllimport) 00111 #endif 00112 #else 00113 #define ILMTHREAD_EXPORT 00114 #endif 00115 00116 namespace IlmThread { 00117 00118 // 00119 // Query function to determine if the current platform supports 00120 // threads AND this library was compiled with threading enabled. 00121 // 00122 00123 ILMTHREAD_EXPORT bool supportsThreads (); 00124 00125 00126 class ILMTHREAD_EXPORT Thread 00127 { 00128 public: 00129 00130 Thread (); 00131 virtual ~Thread (); 00132 00133 void start (); 00134 virtual void run () = 0; 00135 00136 private: 00137 00138 #if defined _WIN32 || defined _WIN64 00139 HANDLE _thread; 00140 #elif HAVE_PTHREAD 00141 pthread_t _thread; 00142 #endif 00143 00144 void operator = (const Thread& t); // not implemented 00145 Thread (const Thread& t); // not implemented 00146 }; 00147 00148 00149 } // namespace IlmThread 00150 00151 #endif