17 #if BT_THREADSAFE && !defined( _WIN32 ) 32 #define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html 33 #endif //_XOPEN_SOURCE 35 #include <semaphore.h> 45 #if __cplusplus >= 201103L 49 int btGetNumHardwareThreads()
56 int btGetNumHardwareThreads()
74 ThreadFunc m_userThreadFunc;
79 sem_t* startSemaphore;
83 sem_t* m_mainSemaphore;
84 unsigned long threadUsed;
87 typedef unsigned long long UINT64;
91 sem_t* m_mainSemaphore;
93 UINT64 m_startedThreadsMask;
94 void startThreads(
const ConstructionInfo& threadInfo );
96 int waitForResponse();
99 btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo );
100 virtual ~btThreadSupportPosix();
102 virtual int getNumWorkerThreads() const
BT_OVERRIDE {
return m_numThreads; }
104 virtual int getCacheFriendlyNumThreads() const
BT_OVERRIDE {
return m_numThreads + 1; }
106 virtual int getLogicalToPhysicalCoreRatio() const
BT_OVERRIDE {
return 1; }
108 virtual void runTask(
int threadIndex,
void* userData )
BT_OVERRIDE;
109 virtual void waitForAllTasks() BT_OVERRIDE;
112 virtual
void deleteCriticalSection(
btCriticalSection* criticalSection ) BT_OVERRIDE;
116 #define checkPThreadFunction(returnValue) \ 117 if(0 != returnValue) { \ 118 printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \ 125 btThreadSupportPosix::btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo )
127 startThreads( threadConstructionInfo );
131 btThreadSupportPosix::~btThreadSupportPosix()
136 #if (defined (__APPLE__)) 137 #define NAMED_SEMAPHORES 141 static sem_t* createSem(
const char* baseName )
143 static int semCount = 0;
144 #ifdef NAMED_SEMAPHORES 147 snprintf( name, 32,
"/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++ );
148 sem_t* tempSem = sem_open( name, O_CREAT, 0600, 0 );
150 if ( tempSem != reinterpret_cast<sem_t *>( SEM_FAILED ) )
161 sem_t* tempSem =
new sem_t;
162 checkPThreadFunction( sem_init( tempSem, 0, 0 ) );
167 static void destroySem( sem_t* semaphore )
169 #ifdef NAMED_SEMAPHORES 170 checkPThreadFunction( sem_close( semaphore ) );
172 checkPThreadFunction( sem_destroy( semaphore ) );
177 static void *threadFunction(
void *argument )
179 btThreadSupportPosix::btThreadStatus* status = ( btThreadSupportPosix::btThreadStatus* )argument;
183 checkPThreadFunction( sem_wait( status->startSemaphore ) );
184 void* userPtr = status->m_userPtr;
189 status->m_userThreadFunc( userPtr );
190 status->m_status = 2;
191 checkPThreadFunction( sem_post( status->m_mainSemaphore ) );
192 status->threadUsed++;
197 status->m_status = 3;
198 checkPThreadFunction( sem_post( status->m_mainSemaphore ) );
199 printf(
"Thread with taskId %i exiting\n", status->m_taskId );
204 printf(
"Thread TERMINATED\n" );
209 void btThreadSupportPosix::runTask(
int threadIndex,
void* userData )
212 btThreadStatus& threadStatus = m_activeThreadStatus[ threadIndex ];
216 threadStatus.m_commandId = 1;
217 threadStatus.m_status = 1;
218 threadStatus.m_userPtr = userData;
219 m_startedThreadsMask |= UINT64( 1 ) << threadIndex;
222 checkPThreadFunction( sem_post( threadStatus.startSemaphore ) );
227 int btThreadSupportPosix::waitForResponse()
235 checkPThreadFunction( sem_wait( m_mainSemaphore ) );
239 for (
size_t t = 0; t < size_t( m_activeThreadStatus.
size() ); ++t )
241 if ( 2 == m_activeThreadStatus[ t ].m_status )
248 btThreadStatus& threadStatus = m_activeThreadStatus[ last ];
250 btAssert( threadStatus.m_status > 1 );
251 threadStatus.m_status = 0;
255 m_startedThreadsMask &= ~( UINT64( 1 ) << last );
261 void btThreadSupportPosix::waitForAllTasks()
263 while ( m_startedThreadsMask )
270 void btThreadSupportPosix::startThreads(
const ConstructionInfo& threadConstructionInfo )
272 m_numThreads = btGetNumHardwareThreads() - 1;
273 printf(
"%s creating %i threads.\n", __FUNCTION__, m_numThreads );
274 m_activeThreadStatus.
resize( m_numThreads );
275 m_startedThreadsMask = 0;
277 m_mainSemaphore = createSem(
"main" );
280 for (
int i = 0; i < m_numThreads; i++ )
282 printf(
"starting thread %d\n", i );
283 btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
284 threadStatus.startSemaphore = createSem(
"threadLocal" );
285 checkPThreadFunction( pthread_create( &threadStatus.thread, NULL, &threadFunction, (
void*) &threadStatus ) );
287 threadStatus.m_userPtr = 0;
288 threadStatus.m_taskId = i;
289 threadStatus.m_commandId = 0;
290 threadStatus.m_status = 0;
291 threadStatus.m_mainSemaphore = m_mainSemaphore;
292 threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
293 threadStatus.threadUsed = 0;
295 printf(
"started thread %d \n", i );
300 void btThreadSupportPosix::stopThreads()
302 for (
size_t t = 0; t < size_t( m_activeThreadStatus.
size() ); ++t )
304 btThreadStatus& threadStatus = m_activeThreadStatus[ t ];
305 printf(
"%s: Thread %i used: %ld\n", __FUNCTION__,
int( t ), threadStatus.threadUsed );
307 threadStatus.m_userPtr = 0;
308 checkPThreadFunction( sem_post( threadStatus.startSemaphore ) );
309 checkPThreadFunction( sem_wait( m_mainSemaphore ) );
311 printf(
"destroy semaphore\n" );
312 destroySem( threadStatus.startSemaphore );
313 printf(
"semaphore destroyed\n" );
314 checkPThreadFunction( pthread_join( threadStatus.thread, 0 ) );
317 printf(
"destroy main semaphore\n" );
318 destroySem( m_mainSemaphore );
319 printf(
"main semaphore destroyed\n" );
320 m_activeThreadStatus.
clear();
325 pthread_mutex_t m_mutex;
328 btCriticalSectionPosix()
330 pthread_mutex_init( &m_mutex, NULL );
332 virtual ~btCriticalSectionPosix()
334 pthread_mutex_destroy( &m_mutex );
339 pthread_mutex_lock( &m_mutex );
341 virtual void unlock()
343 pthread_mutex_unlock( &m_mutex );
350 return new btCriticalSectionPosix();
361 return new btThreadSupportPosix( info );
364 #endif // BT_THREADSAFE && !defined( _WIN32 ) The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
static btThreadSupportInterface * create(const ConstructionInfo &info)
const unsigned int BT_MAX_THREAD_COUNT
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())