00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "OVR_Threads.h"
00018 #include "OVR_Hash.h"
00019 #include "OVR_Log.h"
00020
00021 #ifdef OVR_ENABLE_THREADS
00022
00023
00024 #include <process.h>
00025
00026 namespace OVR {
00027
00028
00029
00030
00031
00032 class MutexImpl : public NewOverrideBase
00033 {
00034
00035 HANDLE hMutexOrSemaphore;
00036 bool Recursive;
00037 volatile unsigned LockCount;
00038
00039 friend class WaitConditionImpl;
00040
00041 public:
00042
00043 MutexImpl(bool recursive = 1);
00044 ~MutexImpl();
00045
00046
00047 void DoLock();
00048 bool TryLock();
00049 void Unlock(Mutex* pmutex);
00050
00051 bool IsLockedByAnotherThread(Mutex* pmutex);
00052 };
00053
00054
00055 MutexImpl::MutexImpl(bool recursive)
00056 {
00057 Recursive = recursive;
00058 LockCount = 0;
00059 hMutexOrSemaphore = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL);
00060 }
00061 MutexImpl::~MutexImpl()
00062 {
00063 CloseHandle(hMutexOrSemaphore);
00064 }
00065
00066
00067
00068 void MutexImpl::DoLock()
00069 {
00070 if (::WaitForSingleObject(hMutexOrSemaphore, INFINITE) != WAIT_OBJECT_0)
00071 return;
00072 LockCount++;
00073 }
00074
00075 bool MutexImpl::TryLock()
00076 {
00077 DWORD ret;
00078 if ((ret=::WaitForSingleObject(hMutexOrSemaphore, 0)) != WAIT_OBJECT_0)
00079 return 0;
00080 LockCount++;
00081 return 1;
00082 }
00083
00084 void MutexImpl::Unlock(Mutex* pmutex)
00085 {
00086 OVR_UNUSED(pmutex);
00087
00088 unsigned lockCount;
00089 LockCount--;
00090 lockCount = LockCount;
00091
00092
00093 if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) :
00094 ReleaseSemaphore(hMutexOrSemaphore, 1, NULL)) != 0)
00095 {
00096
00097 }
00098 }
00099
00100 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
00101 {
00102
00103 if (LockCount == 0)
00104 return 0;
00105 if (!TryLock())
00106 return 1;
00107 Unlock(pmutex);
00108 return 0;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 Mutex::Mutex(bool recursive)
00125 {
00126 pImpl = new MutexImpl(recursive);
00127 }
00128 Mutex::~Mutex()
00129 {
00130 delete pImpl;
00131 }
00132
00133
00134 void Mutex::DoLock()
00135 {
00136 pImpl->DoLock();
00137 }
00138 bool Mutex::TryLock()
00139 {
00140 return pImpl->TryLock();
00141 }
00142 void Mutex::Unlock()
00143 {
00144 pImpl->Unlock(this);
00145 }
00146 bool Mutex::IsLockedByAnotherThread()
00147 {
00148 return pImpl->IsLockedByAnotherThread(this);
00149 }
00150
00151
00152
00153
00154 bool Event::Wait(unsigned delay)
00155 {
00156 Mutex::Locker lock(&StateMutex);
00157
00158
00159 if (delay == OVR_WAIT_INFINITE)
00160 {
00161 while(!State)
00162 StateWaitCondition.Wait(&StateMutex);
00163 }
00164 else if (delay)
00165 {
00166 if (!State)
00167 StateWaitCondition.Wait(&StateMutex, delay);
00168 }
00169
00170 bool state = State;
00171
00172 if (Temporary)
00173 {
00174 Temporary = false;
00175 State = false;
00176 }
00177 return state;
00178 }
00179
00180 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
00181 {
00182 Mutex::Locker lock(&StateMutex);
00183 State = newState;
00184 Temporary = newTemp;
00185 if (mustNotify)
00186 StateWaitCondition.NotifyAll();
00187 }
00188
00189
00190
00191
00192
00193
00194 class WaitConditionImpl : public NewOverrideBase
00195 {
00196
00197 struct EventPoolEntry : public NewOverrideBase
00198 {
00199 HANDLE hEvent;
00200 EventPoolEntry *pNext;
00201 EventPoolEntry *pPrev;
00202 };
00203
00204 Lock WaitQueueLoc;
00205
00206 EventPoolEntry * pFreeEventList;
00207
00208
00209 EventPoolEntry* pQueueHead;
00210 EventPoolEntry* pQueueTail;
00211
00212
00213 EventPoolEntry* GetNewEvent();
00214 void ReleaseEvent(EventPoolEntry* pevent);
00215
00216
00217 void QueuePush(EventPoolEntry* pentry);
00218 EventPoolEntry* QueuePop();
00219 void QueueFindAndRemove(EventPoolEntry* pentry);
00220
00221 public:
00222
00223
00224 WaitConditionImpl();
00225 ~WaitConditionImpl();
00226
00227
00228 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
00229
00230
00231 void Notify();
00232
00233 void NotifyAll();
00234 };
00235
00236
00237
00238 WaitConditionImpl::WaitConditionImpl()
00239 {
00240 pFreeEventList = 0;
00241 pQueueHead =
00242 pQueueTail = 0;
00243 }
00244
00245 WaitConditionImpl::~WaitConditionImpl()
00246 {
00247
00248 EventPoolEntry* p = pFreeEventList;
00249 EventPoolEntry* pentry;
00250
00251 while(p)
00252 {
00253
00254 pentry = p;
00255 p = p->pNext;
00256
00257 ::CloseHandle(pentry->hEvent);
00258 delete pentry;
00259 }
00260
00261
00262
00263 pFreeEventList = 0;
00264 pQueueHead =
00265 pQueueTail = 0;
00266 }
00267
00268
00269
00270 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent()
00271 {
00272 EventPoolEntry* pentry;
00273
00274
00275 if (pFreeEventList)
00276 {
00277 pentry = pFreeEventList;
00278 pFreeEventList = pFreeEventList->pNext;
00279 }
00280 else
00281 {
00282
00283 pentry = new EventPoolEntry;
00284 pentry->pNext = 0;
00285 pentry->pPrev = 0;
00286
00287 pentry->hEvent = ::CreateEvent(NULL, TRUE, 0, NULL);
00288 }
00289
00290 return pentry;
00291 }
00292
00293 void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent)
00294 {
00295
00296 ::ResetEvent(pevent->hEvent);
00297
00298 pevent->pNext = pFreeEventList;
00299 pevent->pPrev = 0;
00300 pFreeEventList = pevent;
00301 }
00302
00303
00304 void WaitConditionImpl::QueuePush(EventPoolEntry* pentry)
00305 {
00306
00307 if (pQueueTail)
00308 {
00309 pentry->pPrev = pQueueTail;
00310 pQueueTail->pNext = pentry;
00311 pentry->pNext = 0;
00312 pQueueTail = pentry;
00313 }
00314 else
00315 {
00316
00317 pentry->pNext =
00318 pentry->pPrev = 0;
00319 pQueueHead =
00320 pQueueTail = pentry;
00321 }
00322 }
00323
00324 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::QueuePop()
00325 {
00326 EventPoolEntry* pentry = pQueueHead;
00327
00328
00329 if (pentry)
00330 {
00331
00332 if (pQueueHead->pNext)
00333 {
00334 pQueueHead = pentry->pNext;
00335 pQueueHead->pPrev = 0;
00336 }
00337 else
00338 {
00339
00340 pQueueTail =
00341 pQueueHead = 0;
00342 }
00343 }
00344 return pentry;
00345 }
00346
00347 void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry)
00348 {
00349
00350 EventPoolEntry* p = pQueueHead;
00351
00352 while(p)
00353 {
00354
00355 if (p == pentry)
00356 {
00357
00358
00359
00360 if (pentry->pPrev)
00361 pentry->pPrev->pNext = pentry->pNext;
00362 else
00363 pQueueHead = pentry->pNext;
00364
00365 if (pentry->pNext)
00366 pentry->pNext->pPrev = pentry->pPrev;
00367 else
00368 pQueueTail = pentry->pPrev;
00369
00370 return;
00371 }
00372
00373
00374 p = p->pNext;
00375 }
00376 }
00377
00378
00379 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
00380 {
00381 bool result = 0;
00382 unsigned i;
00383 unsigned lockCount = pmutex->pImpl->LockCount;
00384 EventPoolEntry* pentry;
00385
00386
00387 if (lockCount == 0)
00388 return 0;
00389
00390
00391 WaitQueueLoc.DoLock();
00392 QueuePush(pentry = GetNewEvent());
00393 WaitQueueLoc.Unlock();
00394
00395
00396 if (pmutex->pImpl->Recursive)
00397 {
00398
00399 pmutex->pImpl->LockCount = 0;
00400 for(i=0; i<lockCount; i++)
00401 ::ReleaseMutex(pmutex->pImpl->hMutexOrSemaphore);
00402 }
00403 else
00404 {
00405 pmutex->pImpl->LockCount = 0;
00406 ::ReleaseSemaphore(pmutex->pImpl->hMutexOrSemaphore, 1, NULL);
00407 }
00408
00409
00410
00411
00412
00413
00414 DWORD waitResult = ::WaitForSingleObject(pentry->hEvent,
00415 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay);
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 WaitQueueLoc.DoLock();
00426 switch(waitResult)
00427 {
00428 case WAIT_ABANDONED:
00429 case WAIT_OBJECT_0:
00430 result = 1;
00431
00432
00433 ReleaseEvent(pentry);
00434 break;
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 default:
00446
00447 QueueFindAndRemove(pentry);
00448 ReleaseEvent(pentry);
00449 }
00450 WaitQueueLoc.Unlock();
00451
00452
00453 for(i=0; i<lockCount; i++)
00454 pmutex->DoLock();
00455
00456
00457 return result;
00458 }
00459
00460
00461 void WaitConditionImpl::Notify()
00462 {
00463 Lock::Locker lock(&WaitQueueLoc);
00464
00465
00466 EventPoolEntry* pentry = QueuePop();
00467 if (pentry)
00468 ::SetEvent(pentry->hEvent);
00469 }
00470
00471
00472 void WaitConditionImpl::NotifyAll()
00473 {
00474 Lock::Locker lock(&WaitQueueLoc);
00475
00476
00477
00478 EventPoolEntry* pentry = QueuePop();
00479 while (pentry)
00480 {
00481 ::SetEvent(pentry->hEvent);
00482 pentry = QueuePop();
00483 }
00484 }
00485
00486
00487
00488
00489
00490 WaitCondition::WaitCondition()
00491 {
00492 pImpl = new WaitConditionImpl;
00493 }
00494 WaitCondition::~WaitCondition()
00495 {
00496 delete pImpl;
00497 }
00498
00499
00500 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay)
00501 {
00502 return pImpl->Wait(pmutex, delay);
00503 }
00504
00505 void WaitCondition::Notify()
00506 {
00507 pImpl->Notify();
00508 }
00509 void WaitCondition::NotifyAll()
00510 {
00511 pImpl->NotifyAll();
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 Thread::Thread(UPInt stackSize, int processor)
00534 {
00535 CreateParams params;
00536 params.stackSize = stackSize;
00537 params.processor = processor;
00538 Init(params);
00539 }
00540
00541 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
00542 int processor, Thread::ThreadState initialState)
00543 {
00544 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
00545 Init(params);
00546 }
00547
00548 Thread::Thread(const CreateParams& params)
00549 {
00550 Init(params);
00551 }
00552 void Thread::Init(const CreateParams& params)
00553 {
00554
00555 ThreadFlags = 0;
00556 ThreadHandle = 0;
00557 IdValue = 0;
00558 ExitCode = 0;
00559 SuspendCount = 0;
00560 StackSize = params.stackSize;
00561 Processor = params.processor;
00562 Priority = params.priority;
00563
00564
00565 ThreadFunction = params.threadFunction;
00566 UserHandle = params.userHandle;
00567 if (params.initialState != NotRunning)
00568 Start(params.initialState);
00569
00570 }
00571
00572 Thread::~Thread()
00573 {
00574
00575
00576
00577
00578
00579 CleanupSystemThread();
00580 ThreadHandle = 0;
00581 }
00582
00583
00584
00585
00586
00587 int Thread::Run()
00588 {
00589
00590 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
00591 }
00592 void Thread::OnExit()
00593 {
00594 }
00595
00596
00597 void Thread::FinishAndRelease()
00598 {
00599
00600 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
00601 ThreadFlags |= OVR_THREAD_FINISHED;
00602
00603
00604
00605 Release();
00606 }
00607
00608
00609
00610
00611 class ThreadList : public NewOverrideBase
00612 {
00613
00614 struct ThreadHashOp
00615 {
00616 UPInt operator()(const Thread* ptr)
00617 {
00618 return (((UPInt)ptr) >> 6) ^ (UPInt)ptr;
00619 }
00620 };
00621
00622 HashSet<Thread*, ThreadHashOp> ThreadSet;
00623 Mutex ThreadMutex;
00624 WaitCondition ThreadsEmpty;
00625
00626 ThreadId RootThreadId;
00627
00628 static ThreadList* volatile pRunningThreads;
00629
00630 void addThread(Thread *pthread)
00631 {
00632 Mutex::Locker lock(&ThreadMutex);
00633 ThreadSet.Add(pthread);
00634 }
00635
00636 void removeThread(Thread *pthread)
00637 {
00638 Mutex::Locker lock(&ThreadMutex);
00639 ThreadSet.Remove(pthread);
00640 if (ThreadSet.GetSize() == 0)
00641 ThreadsEmpty.Notify();
00642 }
00643
00644 void finishAllThreads()
00645 {
00646
00647 OVR_ASSERT(GetCurrentThreadId() == RootThreadId);
00648
00649 Mutex::Locker lock(&ThreadMutex);
00650 while (ThreadSet.GetSize() != 0)
00651 ThreadsEmpty.Wait(&ThreadMutex);
00652 }
00653
00654 public:
00655
00656 ThreadList()
00657 {
00658 RootThreadId = GetCurrentThreadId();
00659 }
00660 ~ThreadList() { }
00661
00662
00663 static void AddRunningThread(Thread *pthread)
00664 {
00665
00666 if (!pRunningThreads)
00667 {
00668 pRunningThreads = new ThreadList;
00669 OVR_ASSERT(pRunningThreads);
00670 }
00671 pRunningThreads->addThread(pthread);
00672 }
00673
00674
00675
00676
00677 static void RemoveRunningThread(Thread *pthread)
00678 {
00679 OVR_ASSERT(pRunningThreads);
00680 pRunningThreads->removeThread(pthread);
00681 }
00682
00683 static void FinishAllThreads()
00684 {
00685
00686 if (pRunningThreads)
00687 {
00688 pRunningThreads->finishAllThreads();
00689 delete pRunningThreads;
00690 pRunningThreads = 0;
00691 }
00692 }
00693 };
00694
00695
00696 ThreadList* volatile ThreadList::pRunningThreads = 0;
00697
00698
00699
00700 void Thread::FinishAllThreads()
00701 {
00702 ThreadList::FinishAllThreads();
00703 }
00704
00705
00706
00707
00708 int Thread::PRun()
00709 {
00710
00711 if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
00712 {
00713 Suspend();
00714 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
00715 }
00716
00717
00718 ExitCode = Run();
00719 return ExitCode;
00720 }
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742 bool Thread::GetExitFlag() const
00743 {
00744 return (ThreadFlags & OVR_THREAD_EXIT) != 0;
00745 }
00746
00747 void Thread::SetExitFlag(bool exitFlag)
00748 {
00749
00750 if (exitFlag)
00751 ThreadFlags |= OVR_THREAD_EXIT;
00752 else
00753 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
00754 }
00755
00756
00757
00758 bool Thread::IsFinished() const
00759 {
00760 return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
00761 }
00762
00763 bool Thread::IsSuspended() const
00764 {
00765 return SuspendCount > 0;
00766 }
00767
00768 Thread::ThreadState Thread::GetThreadState() const
00769 {
00770 if (IsSuspended())
00771 return Suspended;
00772 if (ThreadFlags & OVR_THREAD_STARTED)
00773 return Running;
00774 return NotRunning;
00775 }
00776
00777
00778
00779
00780
00781 int Thread::GetOSPriority(ThreadPriority p)
00782 {
00783 switch(p)
00784 {
00785 case Thread::CriticalPriority: return THREAD_PRIORITY_TIME_CRITICAL;
00786 case Thread::HighestPriority: return THREAD_PRIORITY_HIGHEST;
00787 case Thread::AboveNormalPriority: return THREAD_PRIORITY_ABOVE_NORMAL;
00788 case Thread::NormalPriority: return THREAD_PRIORITY_NORMAL;
00789 case Thread::BelowNormalPriority: return THREAD_PRIORITY_BELOW_NORMAL;
00790 case Thread::LowestPriority: return THREAD_PRIORITY_LOWEST;
00791 case Thread::IdlePriority: return THREAD_PRIORITY_IDLE;
00792 }
00793 return THREAD_PRIORITY_NORMAL;
00794 }
00795
00796
00797 unsigned WINAPI Thread_Win32StartFn(void * phandle)
00798 {
00799 Thread * pthread = (Thread*)phandle;
00800 if (pthread->Processor != -1)
00801 {
00802 DWORD_PTR ret = SetThreadAffinityMask(GetCurrentThread(), (DWORD)pthread->Processor);
00803 if (ret == 0)
00804 OVR_DEBUG_LOG(("Could not set hardware processor for the thread"));
00805 }
00806 BOOL ret = ::SetThreadPriority(GetCurrentThread(), Thread::GetOSPriority(pthread->Priority));
00807 if (ret == 0)
00808 OVR_DEBUG_LOG(("Could not set thread priority"));
00809 OVR_UNUSED(ret);
00810
00811
00812
00813 pthread->IdValue = (ThreadId)::GetCurrentThreadId();
00814
00815 DWORD result = pthread->PRun();
00816
00817 pthread->FinishAndRelease();
00818
00819
00820 ThreadList::RemoveRunningThread(pthread);
00821 return (unsigned) result;
00822 }
00823
00824 bool Thread::Start(ThreadState initialState)
00825 {
00826 if (initialState == NotRunning)
00827 return 0;
00828 if (GetThreadState() != NotRunning)
00829 {
00830 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
00831 return 0;
00832 }
00833
00834
00835 CleanupSystemThread();
00836
00837
00838 AddRef();
00839 ThreadList::AddRunningThread(this);
00840
00841 ExitCode = 0;
00842 SuspendCount = 0;
00843 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
00844 ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize,
00845 Thread_Win32StartFn, this, 0, (unsigned*)&IdValue);
00846
00847
00848 if (ThreadHandle == 0)
00849 {
00850 ThreadFlags = 0;
00851 Release();
00852 ThreadList::RemoveRunningThread(this);
00853 return 0;
00854 }
00855 return 1;
00856 }
00857
00858
00859
00860 bool Thread::Suspend()
00861 {
00862
00863 if (!(ThreadFlags & OVR_THREAD_STARTED))
00864 return 0;
00865
00866 if (::SuspendThread(ThreadHandle) != 0xFFFFFFFF)
00867 {
00868 SuspendCount++;
00869 return 1;
00870 }
00871 return 0;
00872 }
00873
00874
00875 bool Thread::Resume()
00876 {
00877
00878 if (!(ThreadFlags & OVR_THREAD_STARTED))
00879 return 0;
00880
00881
00882 SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1);
00883 if (oldCount >= 1)
00884 {
00885 if (oldCount == 1)
00886 {
00887 if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF)
00888 return 1;
00889 }
00890 else
00891 {
00892 return 1;
00893 }
00894 }
00895 return 0;
00896 }
00897
00898
00899
00900 void Thread::Exit(int exitCode)
00901 {
00902
00903
00904
00905
00906
00907
00908 OnExit();
00909
00910
00911 FinishAndRelease();
00912 ThreadList::RemoveRunningThread(this);
00913
00914
00915 _endthreadex((unsigned)exitCode);
00916 }
00917
00918
00919 void Thread::CleanupSystemThread()
00920 {
00921 if (ThreadHandle != 0)
00922 {
00923 ::CloseHandle(ThreadHandle);
00924 ThreadHandle = 0;
00925 }
00926 }
00927
00928
00929
00930 bool Thread::Sleep(unsigned secs)
00931 {
00932 ::Sleep(secs*1000);
00933 return 1;
00934 }
00935
00936
00937 bool Thread::MSleep(unsigned msecs)
00938 {
00939 ::Sleep(msecs);
00940 return 1;
00941 }
00942
00943 void Thread::SetThreadName( const char* name )
00944 {
00945 #if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING)
00946
00947 typedef struct tagTHREADNAME_INFO {
00948 DWORD dwType;
00949 LPCSTR szName;
00950 DWORD dwThreadID;
00951 DWORD dwFlags;
00952 } THREADNAME_INFO;
00953
00954 THREADNAME_INFO info;
00955
00956 info.dwType = 0x1000;
00957 info.szName = name;
00958 info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId());
00959 info.dwFlags = 0;
00960
00961 __try
00962 {
00963 #ifdef _WIN64
00964 RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info );
00965 #else
00966 RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info );
00967 #endif
00968 }
00969 __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER )
00970 {
00971 }
00972 #endif // OVR_BUILD_SHIPPING
00973 }
00974
00975
00976 int Thread::GetCPUCount()
00977 {
00978 SYSTEM_INFO sysInfo;
00979 GetSystemInfo(&sysInfo);
00980 return (int) sysInfo.dwNumberOfProcessors;
00981 }
00982
00983
00984
00985 ThreadId GetCurrentThreadId()
00986 {
00987 return (ThreadId)::GetCurrentThreadId();
00988 }
00989
00990 }
00991
00992 #endif
00993
00994