17#if BT_THREADSAFE && !defined(_WIN32)
30#define _XOPEN_SOURCE 600
42#if __cplusplus >= 201103L
46int btGetNumHardwareThreads()
53int btGetNumHardwareThreads()
70 ThreadFunc m_userThreadFunc;
75 sem_t* startSemaphore;
79 sem_t* m_mainSemaphore;
80 unsigned long threadUsed;
84 typedef unsigned long long UINT64;
88 sem_t* m_mainSemaphore;
90 UINT64 m_startedThreadsMask;
91 void startThreads(
const ConstructionInfo& threadInfo);
93 int waitForResponse();
96 btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo);
97 virtual ~btThreadSupportPosix();
112#define checkPThreadFunction(returnValue) \
113 if (0 != returnValue) \
115 printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
121btThreadSupportPosix::btThreadSupportPosix(
const ConstructionInfo& threadConstructionInfo)
124 startThreads(threadConstructionInfo);
128btThreadSupportPosix::~btThreadSupportPosix()
135#if (defined(__APPLE__))
136#define NAMED_SEMAPHORES
139static sem_t* createSem(
const char* baseName)
141 static int semCount = 0;
142#ifdef NAMED_SEMAPHORES
145 snprintf(name, 32,
"/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
146 sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
148 if (tempSem !=
reinterpret_cast<sem_t*
>(SEM_FAILED))
159 sem_t* tempSem =
new sem_t;
160 checkPThreadFunction(sem_init(tempSem, 0, 0));
165static void destroySem(sem_t* semaphore)
167#ifdef NAMED_SEMAPHORES
168 checkPThreadFunction(sem_close(semaphore));
170 checkPThreadFunction(sem_destroy(semaphore));
175static void* threadFunction(
void* argument)
177 btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
181 checkPThreadFunction(sem_wait(status->startSemaphore));
182 void* userPtr = status->m_userPtr;
187 status->m_userThreadFunc(userPtr);
188 status->m_cs->lock();
189 status->m_status = 2;
190 status->m_cs->unlock();
191 checkPThreadFunction(sem_post(status->m_mainSemaphore));
192 status->threadUsed++;
197 status->m_cs->lock();
198 status->m_status = 3;
199 status->m_cs->unlock();
200 checkPThreadFunction(sem_post(status->m_mainSemaphore));
209void btThreadSupportPosix::runTask(
int threadIndex,
void* userData)
212 btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
215 threadStatus.m_cs = m_cs;
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));
226int btThreadSupportPosix::waitForResponse()
234 checkPThreadFunction(sem_wait(m_mainSemaphore));
238 for (
size_t t = 0; t < size_t(m_activeThreadStatus.
size()); ++t)
241 bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
250 btThreadStatus& threadStatus = m_activeThreadStatus[last];
252 btAssert(threadStatus.m_status > 1);
253 threadStatus.m_status = 0;
257 m_startedThreadsMask &= ~(UINT64(1) << last);
262void btThreadSupportPosix::waitForAllTasks()
264 while (m_startedThreadsMask)
270void btThreadSupportPosix::startThreads(
const ConstructionInfo& threadConstructionInfo)
272 m_numThreads = btGetNumHardwareThreads() - 1;
273 m_activeThreadStatus.
resize(m_numThreads);
274 m_startedThreadsMask = 0;
276 m_mainSemaphore = createSem(
"main");
279 for (
int i = 0; i < m_numThreads; i++)
281 btThreadStatus& threadStatus = m_activeThreadStatus[i];
282 threadStatus.startSemaphore = createSem(
"threadLocal");
283 threadStatus.m_userPtr = 0;
284 threadStatus.m_cs = m_cs;
285 threadStatus.m_taskId = i;
286 threadStatus.m_commandId = 0;
287 threadStatus.m_status = 0;
288 threadStatus.m_mainSemaphore = m_mainSemaphore;
289 threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
290 threadStatus.threadUsed = 0;
291 checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (
void*)&threadStatus));
297void btThreadSupportPosix::stopThreads()
299 for (
size_t t = 0; t < size_t(m_activeThreadStatus.
size()); ++t)
301 btThreadStatus& threadStatus = m_activeThreadStatus[t];
303 threadStatus.m_userPtr = 0;
304 checkPThreadFunction(sem_post(threadStatus.startSemaphore));
305 checkPThreadFunction(sem_wait(m_mainSemaphore));
307 checkPThreadFunction(pthread_join(threadStatus.thread, 0));
308 destroySem(threadStatus.startSemaphore);
310 destroySem(m_mainSemaphore);
311 m_activeThreadStatus.
clear();
316 pthread_mutex_t m_mutex;
319 btCriticalSectionPosix()
321 pthread_mutex_init(&m_mutex, NULL);
323 virtual ~btCriticalSectionPosix()
325 pthread_mutex_destroy(&m_mutex);
330 pthread_mutex_lock(&m_mutex);
332 virtual void unlock()
334 pthread_mutex_unlock(&m_mutex);
340 return new btCriticalSectionPosix();
350 return new btThreadSupportPosix(info);
const T & btMax(const T &a, const T &b)
const T & btMin(const T &a, const T &b)
const unsigned int BT_MAX_THREAD_COUNT
The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods It...
int size() const
return the number of elements in the array
void resize(int newsize, const T &fillData=T())
void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
virtual int getCacheFriendlyNumThreads() const =0
virtual int getLogicalToPhysicalCoreRatio() const =0
virtual void waitForAllTasks()=0
static btThreadSupportInterface * create(const ConstructionInfo &info)
virtual void runTask(int threadIndex, void *userData)=0
virtual int getNumWorkerThreads() const =0
virtual void deleteCriticalSection(btCriticalSection *criticalSection)=0
virtual btCriticalSection * createCriticalSection()=0