Bullet Collision Detection & Physics Library

Win32ThreadSupport.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2007 Erwin Coumans  http://bulletphysics.com
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the use of this software.
00007 Permission is granted to anyone to use this software for any purpose, 
00008 including commercial applications, and to alter it and redistribute it freely, 
00009 subject to the following restrictions:
00010 
00011 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00012 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00013 3. This notice may not be removed or altered from any source distribution.
00014 */
00015 
00016 #include "Win32ThreadSupport.h"
00017 
00018 #ifdef USE_WIN32_THREADING
00019 
00020 #include <windows.h>
00021 
00022 #include "SpuCollisionTaskProcess.h"
00023 
00024 #include "SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
00025 
00026 
00027 
00030 
00033 Win32ThreadSupport::Win32ThreadSupport(const Win32ThreadConstructionInfo & threadConstructionInfo)
00034 {
00035         m_maxNumTasks = threadConstructionInfo.m_numThreads;
00036         startThreads(threadConstructionInfo);
00037 }
00038 
00040 Win32ThreadSupport::~Win32ThreadSupport()
00041 {
00042         stopSPU();
00043 }
00044 
00045 
00046 
00047 
00048 #include <stdio.h>
00049 
00050 DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
00051 {
00052 
00053         Win32ThreadSupport::btSpuStatus* status = (Win32ThreadSupport::btSpuStatus*)lpParam;
00054 
00055         
00056         while (1)
00057         {
00058                 WaitForSingleObject(status->m_eventStartHandle,INFINITE);
00059                 
00060                 void* userPtr = status->m_userPtr;
00061 
00062                 if (userPtr)
00063                 {
00064                         btAssert(status->m_status);
00065                         status->m_userThreadFunc(userPtr,status->m_lsMemory);
00066                         status->m_status = 2;
00067                         SetEvent(status->m_eventCompletetHandle);
00068                 } else
00069                 {
00070                         //exit Thread
00071                         status->m_status = 3;
00072                         printf("Thread with taskId %i with handle %p exiting\n",status->m_taskId, status->m_threadHandle);
00073                         SetEvent(status->m_eventCompletetHandle);
00074                         break;
00075                 }
00076                 
00077         }
00078 
00079         printf("Thread TERMINATED\n");
00080         return 0;
00081 
00082 }
00083 
00085 void Win32ThreadSupport::sendRequest(uint32_t uiCommand, ppu_address_t uiArgument0, uint32_t taskId)
00086 {
00088         
00090         
00091 
00092 
00093         switch (uiCommand)
00094         {
00095         case    CMD_GATHER_AND_PROCESS_PAIRLIST:
00096                 {
00097 
00098 
00099 //#define SINGLE_THREADED 1
00100 #ifdef SINGLE_THREADED
00101 
00102                         btSpuStatus&    spuStatus = m_activeSpuStatus[0];
00103                         spuStatus.m_userPtr=(void*)uiArgument0;
00104                         spuStatus.m_userThreadFunc(spuStatus.m_userPtr,spuStatus.m_lsMemory);
00105                         HANDLE handle =0;
00106 #else
00107 
00108 
00109                         btSpuStatus&    spuStatus = m_activeSpuStatus[taskId];
00110                         btAssert(taskId>=0);
00111                         btAssert(int(taskId)<m_activeSpuStatus.size());
00112 
00113                         spuStatus.m_commandId = uiCommand;
00114                         spuStatus.m_status = 1;
00115                         spuStatus.m_userPtr = (void*)uiArgument0;
00116 
00118                         SetEvent(spuStatus.m_eventStartHandle);
00119 
00120 #endif //CollisionTask_LocalStoreMemory
00121 
00122                         
00123 
00124                         break;
00125                 }
00126         default:
00127                 {
00129                         btAssert(0);
00130                 }
00131 
00132         };
00133 
00134 
00135 }
00136 
00137 
00139 void Win32ThreadSupport::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
00140 {
00142         
00144 
00145 
00146         btAssert(m_activeSpuStatus.size());
00147 
00148         int last = -1;
00149 #ifndef SINGLE_THREADED
00150         DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
00151         btAssert(res != WAIT_FAILED);
00152         last = res - WAIT_OBJECT_0;
00153 
00154         btSpuStatus& spuStatus = m_activeSpuStatus[last];
00155         btAssert(spuStatus.m_threadHandle);
00156         btAssert(spuStatus.m_eventCompletetHandle);
00157 
00158         //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
00159         btAssert(spuStatus.m_status > 1);
00160         spuStatus.m_status = 0;
00161 
00163         btAssert(last>=0);
00164 
00165 #else
00166         last=0;
00167         btSpuStatus& spuStatus = m_activeSpuStatus[last];
00168 #endif //SINGLE_THREADED
00169 
00170         
00171 
00172         *puiArgument0 = spuStatus.m_taskId;
00173         *puiArgument1 = spuStatus.m_status;
00174 
00175 
00176 }
00177 
00178 
00180 bool Win32ThreadSupport::isTaskCompleted(unsigned int *puiArgument0, unsigned int *puiArgument1, int timeOutInMilliseconds)
00181 {
00183         
00185 
00186 
00187         btAssert(m_activeSpuStatus.size());
00188 
00189         int last = -1;
00190 #ifndef SINGLE_THREADED
00191         DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, timeOutInMilliseconds);
00192         
00193         if ((res != STATUS_TIMEOUT) && (res != WAIT_FAILED))
00194         {
00195                 
00196                 btAssert(res != WAIT_FAILED);
00197                 last = res - WAIT_OBJECT_0;
00198 
00199                 btSpuStatus& spuStatus = m_activeSpuStatus[last];
00200                 btAssert(spuStatus.m_threadHandle);
00201                 btAssert(spuStatus.m_eventCompletetHandle);
00202 
00203                 //WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
00204                 btAssert(spuStatus.m_status > 1);
00205                 spuStatus.m_status = 0;
00206 
00208                 btAssert(last>=0);
00209 
00210         #else
00211                 last=0;
00212                 btSpuStatus& spuStatus = m_activeSpuStatus[last];
00213         #endif //SINGLE_THREADED
00214 
00215                 
00216 
00217                 *puiArgument0 = spuStatus.m_taskId;
00218                 *puiArgument1 = spuStatus.m_status;
00219 
00220                 return true;
00221         } 
00222 
00223         return false;
00224 }
00225 
00226 
00227 void Win32ThreadSupport::startThreads(const Win32ThreadConstructionInfo& threadConstructionInfo)
00228 {
00229 
00230         m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
00231         m_completeHandles.resize(threadConstructionInfo.m_numThreads);
00232 
00233         m_maxNumTasks = threadConstructionInfo.m_numThreads;
00234 
00235         for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
00236         {
00237                 printf("starting thread %d\n",i);
00238 
00239                 btSpuStatus&    spuStatus = m_activeSpuStatus[i];
00240 
00241                 LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
00242                 SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
00243                 LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
00244                 LPVOID lpParameter=&spuStatus;
00245                 DWORD dwCreationFlags=0;
00246                 LPDWORD lpThreadId=0;
00247 
00248                 spuStatus.m_userPtr=0;
00249 
00250                 sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
00251                 spuStatus.m_eventStartHandle = CreateEventA (0,false,false,spuStatus.m_eventStartHandleName);
00252 
00253                 sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
00254                 spuStatus.m_eventCompletetHandle = CreateEventA (0,false,false,spuStatus.m_eventCompletetHandleName);
00255 
00256                 m_completeHandles[i] = spuStatus.m_eventCompletetHandle;
00257 
00258                 HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter, dwCreationFlags,lpThreadId);
00259                 SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
00260                 //SetThreadPriority(handle,THREAD_PRIORITY_TIME_CRITICAL);
00261 
00262                 SetThreadAffinityMask(handle, 1<<i);
00263 
00264                 spuStatus.m_taskId = i;
00265                 spuStatus.m_commandId = 0;
00266                 spuStatus.m_status = 0;
00267                 spuStatus.m_threadHandle = handle;
00268                 spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
00269                 spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
00270 
00271                 printf("started thread %d with threadHandle %p\n",i,handle);
00272                 
00273         }
00274 
00275 }
00276 
00277 void Win32ThreadSupport::startSPU()
00278 {
00279 }
00280 
00281 
00283 void Win32ThreadSupport::stopSPU()
00284 {
00285         int i;
00286         for (i=0;i<m_activeSpuStatus.size();i++)
00287         {
00288                 btSpuStatus& spuStatus = m_activeSpuStatus[i];
00289                 if (spuStatus.m_status>0)
00290                 {
00291                         WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
00292                 }
00293                 
00294 
00295                 spuStatus.m_userPtr = 0;
00296                 SetEvent(spuStatus.m_eventStartHandle);
00297                 WaitForSingleObject(spuStatus.m_eventCompletetHandle, INFINITE);
00298 
00299                 CloseHandle(spuStatus.m_eventCompletetHandle);
00300                 CloseHandle(spuStatus.m_eventStartHandle);
00301                 CloseHandle(spuStatus.m_threadHandle);
00302         }
00303 
00304         m_activeSpuStatus.clear();
00305         m_completeHandles.clear();
00306 
00307 }
00308 
00309 
00310 
00311 class btWin32Barrier : public btBarrier
00312 {
00313 private:
00314         CRITICAL_SECTION mExternalCriticalSection;
00315         CRITICAL_SECTION mLocalCriticalSection;
00316         HANDLE mRunEvent,mNotifyEvent;
00317         int mCounter,mEnableCounter;
00318         int mMaxCount;
00319 
00320 public:
00321         btWin32Barrier()
00322         {
00323                 mCounter = 0;
00324                 mMaxCount = 1;
00325                 mEnableCounter = 0;
00326                 InitializeCriticalSection(&mExternalCriticalSection);
00327                 InitializeCriticalSection(&mLocalCriticalSection);
00328                 mRunEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00329                 mNotifyEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
00330         }
00331 
00332         virtual ~btWin32Barrier()
00333         {
00334                 DeleteCriticalSection(&mExternalCriticalSection);
00335                 DeleteCriticalSection(&mLocalCriticalSection);
00336                 CloseHandle(mRunEvent);
00337                 CloseHandle(mNotifyEvent);
00338         }
00339 
00340         void sync()
00341         {
00342                 int eventId;
00343 
00344                 EnterCriticalSection(&mExternalCriticalSection);
00345 
00346                 //PFX_PRINTF("enter taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter);
00347 
00348                 if(mEnableCounter > 0) {
00349                         ResetEvent(mNotifyEvent);
00350                         LeaveCriticalSection(&mExternalCriticalSection);
00351                         WaitForSingleObject(mNotifyEvent,INFINITE); 
00352                         EnterCriticalSection(&mExternalCriticalSection);
00353                 }
00354 
00355                 eventId = mCounter;
00356                 mCounter++;
00357 
00358                 if(eventId == mMaxCount-1) {
00359                         SetEvent(mRunEvent);
00360 
00361                         mEnableCounter = mCounter-1;
00362                         mCounter = 0;
00363                 }
00364                 else {
00365                         ResetEvent(mRunEvent);
00366                         LeaveCriticalSection(&mExternalCriticalSection);
00367                         WaitForSingleObject(mRunEvent,INFINITE); 
00368                         EnterCriticalSection(&mExternalCriticalSection);
00369                         mEnableCounter--;
00370                 }
00371 
00372                 if(mEnableCounter == 0) {
00373                         SetEvent(mNotifyEvent);
00374                 }
00375 
00376                 //PFX_PRINTF("leave taskId %d count %d stage %d phase %d mEnableCounter %d\n",taskId,mCounter,debug&0xff,debug>>16,mEnableCounter);
00377 
00378                 LeaveCriticalSection(&mExternalCriticalSection);
00379         }
00380 
00381         virtual void setMaxCount(int n) {mMaxCount = n;}
00382         virtual int  getMaxCount() {return mMaxCount;}
00383 };
00384 
00385 class btWin32CriticalSection : public btCriticalSection
00386 {
00387 private:
00388         CRITICAL_SECTION mCriticalSection;
00389 
00390 public:
00391         btWin32CriticalSection()
00392         {
00393                 InitializeCriticalSection(&mCriticalSection);
00394         }
00395 
00396         ~btWin32CriticalSection()
00397         {
00398                 DeleteCriticalSection(&mCriticalSection);
00399         }
00400 
00401         unsigned int getSharedParam(int i)
00402         {
00403                 btAssert(i>=0&&i<31);
00404                 return mCommonBuff[i+1];
00405         }
00406 
00407         void setSharedParam(int i,unsigned int p)
00408         {
00409                 btAssert(i>=0&&i<31);
00410                 mCommonBuff[i+1] = p;
00411         }
00412 
00413         void lock()
00414         {
00415                 EnterCriticalSection(&mCriticalSection);
00416                 mCommonBuff[0] = 1;
00417         }
00418 
00419         void unlock()
00420         {
00421                 mCommonBuff[0] = 0;
00422                 LeaveCriticalSection(&mCriticalSection);
00423         }
00424 };
00425 
00426 
00427 btBarrier*      Win32ThreadSupport::createBarrier()
00428 {
00429         unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32Barrier),16);
00430         btWin32Barrier* barrier = new(mem) btWin32Barrier();
00431         barrier->setMaxCount(getNumTasks());
00432         return barrier;
00433 }
00434 
00435 btCriticalSection* Win32ThreadSupport::createCriticalSection()
00436 {
00437         unsigned char* mem = (unsigned char*) btAlignedAlloc(sizeof(btWin32CriticalSection),16);
00438         btWin32CriticalSection* cs = new(mem) btWin32CriticalSection();
00439         return cs;
00440 }
00441 
00442 
00443 
00444 #endif //USE_WIN32_THREADING
00445 
00446