1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/////////////////////////////////////////////////////////////////////////// 2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas 4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Digital Ltd. LLC 5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// All rights reserved. 7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without 9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// modification, are permitted provided that the following conditions are 10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// met: 11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistributions of source code must retain the above copyright 12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// notice, this list of conditions and the following disclaimer. 13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Redistributions in binary form must reproduce the above 14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// copyright notice, this list of conditions and the following disclaimer 15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// in the documentation and/or other materials provided with the 16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// distribution. 17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// * Neither the name of Industrial Light & Magic nor the names of 18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// its contributors may be used to endorse or promote products derived 19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// from this software without specific prior written permission. 20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/////////////////////////////////////////////////////////////////////////// 34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#ifndef INCLUDED_ILM_THREAD_H 36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define INCLUDED_ILM_THREAD_H 37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//----------------------------------------------------------------------------- 39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// class Thread 41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Class Thread is a portable interface to a system-dependent thread 43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// primitive. In order to make a thread actually do something useful, 44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// you must derive a subclass from class Thread and implement the 45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// run() function. If the operating system supports threading then 46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the run() function will be executed int a new thread. 47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// The actual creation of the thread is done by the start() routine 49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// which then calls the run() function. In general the start() 50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// routine should be called from the constructor of the derived class. 51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// The base-class thread destructor will join/destroy the thread. 53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// IMPORTANT: Due to the mechanisms that encapsulate the low-level 55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// threading primitives in a C++ class there is a race condition 56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// with code resembling the following: 57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// { 59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// WorkerThread myThread; 60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// } // myThread goes out of scope, is destroyed 61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// // and the thread is joined 62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// The race is between the parent thread joining the child thread 64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// in the destructor of myThread, and the run() function in the 65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// child thread. If the destructor gets executed first then run() 66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// will be called with an invalid "this" pointer. 67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This issue can be fixed by using a Semaphore to keep track of 69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// whether the run() function has already been called. You can 70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// include a Semaphore member variable within your derived class 71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// which you post() on in the run() function, and wait() on in the 72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// destructor before the thread is joined. Alternatively you could 73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// do something like this: 74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Semaphore runStarted; 76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// void WorkerThread::run () 78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// { 79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// runStarted.post() 80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// // do some work 81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// ... 82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// } 83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// { 85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// WorkerThread myThread; 86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// runStarted.wait (); // ensure that we have started 87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// // the run function 88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// } // myThread goes out of scope, is destroyed 89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// // and the thread is joined 90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//----------------------------------------------------------------------------- 92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "IlmBaseConfig.h" 94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined _WIN32 || defined _WIN64 96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #ifdef NOMINMAX 97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #undef NOMINMAX 98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #endif 99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #define NOMINMAX 100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #include <windows.h> 101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #include <process.h> 102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#elif HAVE_PTHREAD 103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #include <pthread.h> 104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined(OPENEXR_DLL) && !defined(ZENO_STATIC) 107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #ifdef ILMTHREAD_EXPORTS 108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #define ILMTHREAD_EXPORT __declspec(dllexport) 109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #else 110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #define ILMTHREAD_EXPORT __declspec(dllimport) 111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #endif 112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#else 113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #define ILMTHREAD_EXPORT 114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace IlmThread { 117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Query function to determine if the current platform supports 120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// threads AND this library was compiled with threading enabled. 121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// 122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 123793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerILMTHREAD_EXPORT bool supportsThreads (); 124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerclass ILMTHREAD_EXPORT Thread 127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{ 128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler public: 129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Thread (); 131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual ~Thread (); 132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void start (); 134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler virtual void run () = 0; 135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler private: 137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #if defined _WIN32 || defined _WIN64 139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler HANDLE _thread; 140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #elif HAVE_PTHREAD 141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler pthread_t _thread; 142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler #endif 143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler void operator = (const Thread& t); // not implemented 145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler Thread (const Thread& t); // not implemented 146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}; 147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} // namespace IlmThread 150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler 151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif 152