Home | History | Annotate | Download | only in IlmThread
      1 ///////////////////////////////////////////////////////////////////////////
      2 //
      3 // Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
      4 // Digital Ltd. LLC
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions are
     10 // met:
     11 // *       Redistributions of source code must retain the above copyright
     12 // notice, this list of conditions and the following disclaimer.
     13 // *       Redistributions in binary form must reproduce the above
     14 // copyright notice, this list of conditions and the following disclaimer
     15 // in the documentation and/or other materials provided with the
     16 // distribution.
     17 // *       Neither the name of Industrial Light & Magic nor the names of
     18 // its contributors may be used to endorse or promote products derived
     19 // from this software without specific prior written permission.
     20 //
     21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32 //
     33 ///////////////////////////////////////////////////////////////////////////
     34 
     35 #ifndef INCLUDED_ILM_THREAD_H
     36 #define INCLUDED_ILM_THREAD_H
     37 
     38 //-----------------------------------------------------------------------------
     39 //
     40 //	class Thread
     41 //
     42 //	Class Thread is a portable interface to a system-dependent thread
     43 //	primitive.  In order to make a thread actually do something useful,
     44 //	you must derive a subclass from class Thread and implement the
     45 //	run() function.  If the operating system supports threading then
     46 //	the run() function will be executed int a new thread.
     47 //
     48 //	The actual creation of the thread is done by the start() routine
     49 //	which then calls the run() function.  In general the start()
     50 //	routine should be called from the constructor of the derived class.
     51 //
     52 //	The base-class thread destructor will join/destroy the thread.
     53 //
     54 //	IMPORTANT: Due to the mechanisms that encapsulate the low-level
     55 //	threading primitives in a C++ class there is a race condition
     56 //	with code resembling the following:
     57 //
     58 //	    {
     59 //		WorkerThread myThread;
     60 //	    } // myThread goes out of scope, is destroyed
     61 //	      // and the thread is joined
     62 //
     63 //	The race is between the parent thread joining the child thread
     64 //	in the destructor of myThread, and the run() function in the
     65 //	child thread.  If the destructor gets executed first then run()
     66 //	will be called with an invalid "this" pointer.
     67 //
     68 //	This issue can be fixed by using a Semaphore to keep track of
     69 //	whether the run() function has already been called.  You can
     70 //	include a Semaphore member variable within your derived class
     71 //	which you post() on in the run() function, and wait() on in the
     72 //	destructor before the thread is joined.  Alternatively you could
     73 //	do something like this:
     74 //
     75 //	    Semaphore runStarted;
     76 //
     77 //	    void WorkerThread::run ()
     78 //	    {
     79 //		runStarted.post()
     80 //		// do some work
     81 //		...
     82 //	    }
     83 //
     84 //	    {
     85 //		WorkerThread myThread;
     86 //		runStarted.wait ();    // ensure that we have started
     87 //				       // the run function
     88 //	    } // myThread goes out of scope, is destroyed
     89 //	      // and the thread is joined
     90 //
     91 //-----------------------------------------------------------------------------
     92 
     93 #include "IlmBaseConfig.h"
     94 
     95 #if defined _WIN32 || defined _WIN64
     96     #ifdef NOMINMAX
     97         #undef NOMINMAX
     98     #endif
     99     #define NOMINMAX
    100     #include <windows.h>
    101     #include <process.h>
    102 #elif HAVE_PTHREAD
    103     #include <pthread.h>
    104 #endif
    105 
    106 #if defined(OPENEXR_DLL) && !defined(ZENO_STATIC)
    107     #ifdef ILMTHREAD_EXPORTS
    108     #define ILMTHREAD_EXPORT __declspec(dllexport)
    109     #else
    110     #define ILMTHREAD_EXPORT __declspec(dllimport)
    111     #endif
    112 #else
    113     #define ILMTHREAD_EXPORT
    114 #endif
    115 
    116 namespace IlmThread {
    117 
    118 //
    119 // Query function to determine if the current platform supports
    120 // threads AND this library was compiled with threading enabled.
    121 //
    122 
    123 ILMTHREAD_EXPORT bool supportsThreads ();
    124 
    125 
    126 class ILMTHREAD_EXPORT Thread
    127 {
    128   public:
    129 
    130     Thread ();
    131     virtual ~Thread ();
    132 
    133     void		start ();
    134     virtual void	run () = 0;
    135 
    136   private:
    137 
    138     #if defined _WIN32 || defined _WIN64
    139     HANDLE _thread;
    140     #elif HAVE_PTHREAD
    141     pthread_t _thread;
    142     #endif
    143 
    144     void operator = (const Thread& t);	// not implemented
    145     Thread (const Thread& t);		// not implemented
    146 };
    147 
    148 
    149 } // namespace IlmThread
    150 
    151 #endif
    152