TuttleOFX
1
|
00001 #include "OfxhMultiThreadSuite.hpp" 00002 #include "OfxhCore.hpp" 00003 00004 #include <boost/thread/thread.hpp> 00005 #include <boost/thread/recursive_mutex.hpp> 00006 #include <boost/thread/tss.hpp> 00007 #include <boost/bind.hpp> 00008 00009 struct OfxMutex 00010 { 00011 boost::recursive_mutex _mutex; 00012 }; 00013 00014 namespace tuttle { 00015 namespace host { 00016 namespace ofx { 00017 00018 namespace { 00019 00020 struct ThreadSpecificData 00021 { 00022 ThreadSpecificData( unsigned int threadIndex ) : _index( 0 ) {} 00023 unsigned int _index; 00024 }; 00025 00026 boost::thread_specific_ptr<ThreadSpecificData> ptr; 00027 00028 void launchThread( OfxThreadFunctionV1 func, 00029 unsigned int threadIndex, 00030 unsigned int threadMax, 00031 void* customArg ) 00032 { 00033 ptr.reset( new ThreadSpecificData( threadIndex ) ); 00034 func( threadIndex, threadMax, customArg ); 00035 } 00036 00037 OfxStatus multiThread( OfxThreadFunctionV1 func, 00038 const unsigned int nThreads, 00039 void* customArg ) 00040 { 00041 if( nThreads == 0 ) 00042 { 00043 return kOfxStatErrValue; 00044 } 00045 else if( nThreads == 1 ) 00046 { 00047 func( 0, 1, customArg ); 00048 } 00049 else 00050 { 00051 boost::thread_group group; 00052 for( unsigned int i = 0; i < nThreads; ++i ) 00053 { 00054 group.create_thread( boost::bind( launchThread, func, i, nThreads, customArg ) ); 00055 } 00056 group.join_all(); 00057 } 00058 return kOfxStatOK; 00059 } 00060 00061 OfxStatus multiThreadNumCPUs( unsigned int* const nCPUs ) 00062 { 00063 // *nCPUs = 1; /// @todo tuttle: needs to have an option to disable multithreading (force only one cpu). 00064 *nCPUs = boost::thread::hardware_concurrency(); 00065 TUTTLE_TLOG( TUTTLE_INFO, "[Multi thread] CPUs used: " << *nCPUs ); 00066 return kOfxStatOK; 00067 } 00068 00069 OfxStatus multiThreadIndex( unsigned int* const threadIndex ) 00070 { 00071 // *threadIndex = boost::this_thread::get_id(); // we don't want a global thead id, but the thead index inside a node multithread process. 00072 if( ptr.get() != NULL ) 00073 { 00074 *threadIndex = 0; 00075 return kOfxStatFailed; 00076 } 00077 *threadIndex = ptr->_index; 00078 return kOfxStatOK; 00079 } 00080 00081 int multiThreadIsSpawnedThread( void ) 00082 { 00083 return ptr.get() != NULL; 00084 } 00085 00086 /** 00087 * @todo tuttle: support lockCount init value. 00088 */ 00089 OfxStatus mutexCreate( OfxMutexHandle* mutex, const int lockCount ) 00090 { 00091 *mutex = new OfxMutex(); 00092 return kOfxStatOK; 00093 } 00094 00095 OfxStatus mutexDestroy( OfxMutexHandle mutex ) 00096 { 00097 if( mutex == NULL ) 00098 return kOfxStatErrBadHandle; 00099 delete mutex; 00100 mutex = NULL; 00101 return kOfxStatOK; 00102 } 00103 00104 OfxStatus mutexLock( OfxMutexHandle mutex ) 00105 { 00106 if( mutex == NULL ) 00107 return kOfxStatErrBadHandle; 00108 mutex->_mutex.lock(); 00109 return kOfxStatOK; 00110 } 00111 00112 OfxStatus mutexUnLock( OfxMutexHandle mutex ) 00113 { 00114 if( mutex == NULL ) 00115 return kOfxStatErrBadHandle; 00116 mutex->_mutex.unlock(); 00117 return kOfxStatOK; 00118 } 00119 00120 OfxStatus mutexTryLock( OfxMutexHandle mutex ) 00121 { 00122 if( mutex == NULL ) 00123 return kOfxStatErrBadHandle; 00124 if( mutex->_mutex.try_lock() ) 00125 return kOfxStatOK; 00126 return kOfxStatFailed; 00127 } 00128 00129 struct OfxMultiThreadSuiteV1 gSingleThreadedSuite = 00130 { 00131 multiThread, 00132 multiThreadNumCPUs, 00133 multiThreadIndex, 00134 multiThreadIsSpawnedThread, 00135 mutexCreate, 00136 mutexDestroy, 00137 mutexLock, 00138 mutexUnLock, 00139 mutexTryLock 00140 }; 00141 00142 } 00143 00144 void* getMultithreadSuite( const int version ) 00145 { 00146 if( version == 1 ) 00147 return &gSingleThreadedSuite; 00148 return NULL; 00149 } 00150 00151 } 00152 } 00153 } 00154