OVR_ThreadsWinAPI.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   OVR_ThreadsWinAPI.cpp
00004 Platform    :   WinAPI
00005 Content     :   Windows specific thread-related (safe) functionality
00006 Created     :   September 19, 2012
00007 Notes       : 
00008 
00009 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00010 
00011 Use of this software is subject to the terms of the Oculus license
00012 agreement provided at the time of installation or download, or which
00013 otherwise accompanies this software in either electronic or hard copy form.
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 // For _beginthreadex / _endtheadex
00024 #include <process.h>
00025 
00026 namespace OVR {
00027 
00028 
00029 //-----------------------------------------------------------------------------------
00030 // *** Internal Mutex implementation class
00031 
00032 class MutexImpl : public NewOverrideBase
00033 {
00034     // System mutex or semaphore
00035     HANDLE            hMutexOrSemaphore;
00036     bool              Recursive;
00037     volatile unsigned LockCount;
00038     
00039     friend class WaitConditionImpl;
00040 
00041 public:
00042     // Constructor/destructor
00043     MutexImpl(bool recursive = 1);
00044     ~MutexImpl();
00045 
00046     // Locking functions
00047     void                DoLock();
00048     bool                TryLock();
00049     void                Unlock(Mutex* pmutex);
00050     // Returns 1 if the mutes is currently locked
00051     bool                IsLockedByAnotherThread(Mutex* pmutex);
00052 };
00053 
00054 // *** Constructor/destructor
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 // Lock and try lock
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     // Release mutex
00093     if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) :
00094                      ReleaseSemaphore(hMutexOrSemaphore, 1, NULL))  != 0)
00095     {
00096         // This used to call Wait handlers if lockCount == 0.
00097     }
00098 }
00099 
00100 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
00101 {
00102     // There could be multiple interpretations of IsLocked with respect to current thread
00103     if (LockCount == 0)
00104         return 0;
00105     if (!TryLock())
00106         return 1;
00107     Unlock(pmutex);
00108     return 0;
00109 }
00110 
00111 /*
00112 bool    MutexImpl::IsSignaled() const
00113 {
00114     // An mutex is signaled if it is not locked ANYWHERE
00115     // Note that this is different from IsLockedByAnotherThread function,
00116     // that takes current thread into account
00117     return LockCount == 0;
00118 }
00119 */
00120 
00121 
00122 // *** Actual Mutex class implementation
00123 
00124 Mutex::Mutex(bool recursive)
00125 {    
00126     pImpl = new MutexImpl(recursive);
00127 }
00128 Mutex::~Mutex()
00129 {
00130     delete pImpl;
00131 }
00132 
00133 // Lock and try lock
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 // ***** Event
00153 
00154 bool Event::Wait(unsigned delay)
00155 {
00156     Mutex::Locker lock(&StateMutex);
00157 
00158     // Do the correct amount of waiting
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     // Take care of temporary 'pulsing' of a state
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 // ***** Win32 Wait Condition Implementation
00192 
00193 // Internal implementation class
00194 class WaitConditionImpl : public NewOverrideBase
00195 {   
00196     // Event pool entries for extra events
00197     struct EventPoolEntry  : public NewOverrideBase
00198     {
00199         HANDLE          hEvent;
00200         EventPoolEntry  *pNext;
00201         EventPoolEntry  *pPrev;
00202     };
00203     
00204     Lock                WaitQueueLoc;
00205     // Stores free events that can be used later
00206     EventPoolEntry  *   pFreeEventList;
00207     
00208     // A queue of waiting objects to be signaled    
00209     EventPoolEntry*     pQueueHead;
00210     EventPoolEntry*     pQueueTail;
00211 
00212     // Allocation functions for free events
00213     EventPoolEntry*     GetNewEvent();
00214     void                ReleaseEvent(EventPoolEntry* pevent);
00215 
00216     // Queue operations
00217     void                QueuePush(EventPoolEntry* pentry);
00218     EventPoolEntry*     QueuePop();
00219     void                QueueFindAndRemove(EventPoolEntry* pentry);
00220 
00221 public:
00222 
00223     // Constructor/destructor
00224     WaitConditionImpl();
00225     ~WaitConditionImpl();
00226 
00227     // Release mutex and wait for condition. The mutex is re-acqured after the wait.
00228     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
00229 
00230     // Notify a condition, releasing at one object waiting
00231     void    Notify();
00232     // Notify a condition, releasing all objects waiting
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     // Free all the resources
00248     EventPoolEntry* p       = pFreeEventList;
00249     EventPoolEntry* pentry;
00250 
00251     while(p)
00252     {
00253         // Move to next
00254         pentry = p;
00255         p = p->pNext;
00256         // Delete old
00257         ::CloseHandle(pentry->hEvent);
00258         delete pentry;  
00259     }   
00260     // Shouldn't we also consider the queue?
00261 
00262     // To be safe
00263     pFreeEventList  = 0;
00264     pQueueHead      =
00265     pQueueTail      = 0;
00266 }
00267 
00268 
00269 // Allocation functions for free events
00270 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent()
00271 {
00272     EventPoolEntry* pentry;
00273 
00274     // If there are any free nodes, use them
00275     if (pFreeEventList)
00276     {
00277         pentry          = pFreeEventList;
00278         pFreeEventList  = pFreeEventList->pNext;        
00279     }
00280     else
00281     {
00282         // Allocate a new node
00283         pentry          = new EventPoolEntry;
00284         pentry->pNext   = 0;
00285         pentry->pPrev   = 0;
00286         // Non-signaled manual event
00287         pentry->hEvent  = ::CreateEvent(NULL, TRUE, 0, NULL);
00288     }
00289     
00290     return pentry;
00291 }
00292 
00293 void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent)
00294 {
00295     // Mark event as non-signaled
00296     ::ResetEvent(pevent->hEvent);
00297     // And add it to free pool
00298     pevent->pNext   = pFreeEventList;
00299     pevent->pPrev   = 0;
00300     pFreeEventList  = pevent;
00301 }
00302 
00303 // Queue operations
00304 void WaitConditionImpl::QueuePush(EventPoolEntry* pentry)
00305 {
00306     // Items already exist? Just add to tail
00307     if (pQueueTail)
00308     {
00309         pentry->pPrev       = pQueueTail;
00310         pQueueTail->pNext   = pentry;
00311         pentry->pNext       = 0;        
00312         pQueueTail          = pentry;       
00313     }
00314     else
00315     {
00316         // No items in queue
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     // No items, null pointer
00329     if (pentry)
00330     {
00331         // More items after this one? just grab the first item
00332         if (pQueueHead->pNext)
00333         {       
00334             pQueueHead  = pentry->pNext;
00335             pQueueHead->pPrev = 0;      
00336         }
00337         else
00338         {
00339             // Last item left
00340             pQueueTail =
00341             pQueueHead = 0;
00342         }
00343     }   
00344     return pentry;
00345 }
00346 
00347 void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry)
00348 {
00349     // Do an exhaustive search looking for an entry
00350     EventPoolEntry* p = pQueueHead;
00351 
00352     while(p)
00353     {
00354         // Entry found? Remove.
00355         if (p == pentry)
00356         {
00357             
00358             // Remove the node form the list
00359             // Prev link
00360             if (pentry->pPrev)
00361                 pentry->pPrev->pNext = pentry->pNext;
00362             else
00363                 pQueueHead = pentry->pNext;
00364             // Next link
00365             if (pentry->pNext)
00366                 pentry->pNext->pPrev = pentry->pPrev;
00367             else
00368                 pQueueTail = pentry->pPrev;
00369             // Done
00370             return;
00371         }
00372 
00373         // Move to next item
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     // Mutex must have been locked
00387     if (lockCount == 0)
00388         return 0;
00389     
00390     // Add an object to the wait queue
00391     WaitQueueLoc.DoLock();
00392     QueuePush(pentry = GetNewEvent());
00393     WaitQueueLoc.Unlock();
00394 
00395     // Finally, release a mutex or semaphore
00396     if (pmutex->pImpl->Recursive)
00397     {
00398         // Release the recursive mutex N times
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     // Note that there is a gap here between mutex.Unlock() and Wait(). However,
00410     // if notify() comes in at this point in the other thread it will set our
00411     // corresponding event so wait will just fall through, as expected.
00412 
00413     // Block and wait on the event
00414     DWORD waitResult = ::WaitForSingleObject(pentry->hEvent,
00415                             (delay == OVR_WAIT_INFINITE) ? INFINITE : delay);
00416     /*
00417 repeat_wait:
00418     DWORD waitResult =
00419 
00420     ::MsgWaitForMultipleObjects(1, &pentry->hEvent, FALSE,
00421                                 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay,
00422                                 QS_ALLINPUT);
00423     */
00424 
00425     WaitQueueLoc.DoLock();
00426     switch(waitResult)
00427     {
00428         case WAIT_ABANDONED:
00429         case WAIT_OBJECT_0: 
00430             result = 1;
00431             // Wait was successful, therefore the event entry should already be removed
00432             // So just add entry back to a free list
00433             ReleaseEvent(pentry);
00434             break;
00435             /*
00436         case WAIT_OBJECT_0 + 1:
00437             // Messages in WINDOWS queue
00438             {
00439                 MSG msg;
00440                 PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);             
00441                 WaitQueueLoc.Unlock();
00442                 goto repeat_wait;
00443             }
00444             break; */
00445         default:
00446             // Timeout, our entry should still be in a queue
00447             QueueFindAndRemove(pentry);
00448             ReleaseEvent(pentry);
00449     }
00450     WaitQueueLoc.Unlock();
00451 
00452     // Re-aquire the mutex
00453     for(i=0; i<lockCount; i++)
00454         pmutex->DoLock(); 
00455 
00456     // Return the result
00457     return result;
00458 }
00459 
00460 // Notify a condition, releasing the least object in a queue
00461 void WaitConditionImpl::Notify()
00462 {
00463     Lock::Locker   lock(&WaitQueueLoc);
00464     
00465     // Pop last entry & signal it
00466     EventPoolEntry* pentry = QueuePop();    
00467     if (pentry)
00468         ::SetEvent(pentry->hEvent); 
00469 }
00470 
00471 // Notify a condition, releasing all objects waiting
00472 void WaitConditionImpl::NotifyAll()
00473 {
00474     Lock::Locker   lock(&WaitQueueLoc);
00475 
00476     // Pop and signal all events
00477     // NOTE : There is no need to release the events, it's the waiters job to do so 
00478     EventPoolEntry* pentry = QueuePop();
00479     while (pentry)
00480     {
00481         ::SetEvent(pentry->hEvent);
00482         pentry = QueuePop();
00483     }
00484 }
00485 
00486 
00487 
00488 // *** Actual implementation of WaitCondition
00489 
00490 WaitCondition::WaitCondition()
00491 {
00492     pImpl = new WaitConditionImpl;
00493 }
00494 WaitCondition::~WaitCondition()
00495 {
00496     delete pImpl;
00497 }
00498     
00499 // Wait without a mutex
00500 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
00501 {
00502     return pImpl->Wait(pmutex, delay);
00503 }
00504 // Notification
00505 void    WaitCondition::Notify()
00506 {
00507     pImpl->Notify();
00508 }
00509 void    WaitCondition::NotifyAll()
00510 {
00511     pImpl->NotifyAll();
00512 }
00513 
00514 
00515 
00516 //-----------------------------------------------------------------------------------
00517 // ***** Thread Class
00518 
00519 //  Per-thread variable
00520 //  MA: Don't use TLS for now - portability issues with DLLs, etc.
00521 /*
00522 #if !defined(OVR_CC_MSVC) || (OVR_CC_MSVC < 1300)
00523 __declspec(thread)  Thread*    pCurrentThread      = 0;
00524 #else
00525 #pragma data_seg(".tls$")
00526 __declspec(thread)  Thread*    pCurrentThread      = 0;
00527 #pragma data_seg(".rwdata")
00528 #endif
00529 */
00530 
00531 // *** Thread constructors.
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     // Clear the variables    
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     // Clear Function pointers
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     // Thread should not running while object is being destroyed,
00575     // this would indicate ref-counting issue.
00576     //OVR_ASSERT(IsRunning() == 0);
00577   
00578     // Clean up thread.    
00579     CleanupSystemThread();
00580     ThreadHandle = 0;
00581 }
00582 
00583 
00584 // *** Overridable User functions.
00585 
00586 // Default Run implementation
00587 int Thread::Run()
00588 {
00589     // Call pointer to function, if available.    
00590     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
00591 }
00592 void Thread::OnExit()
00593 {   
00594 }
00595 
00596 // Finishes the thread and releases internal reference to it.
00597 void Thread::FinishAndRelease()
00598 {
00599     // Note: thread must be US.
00600     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
00601     ThreadFlags |= OVR_THREAD_FINISHED;
00602 
00603     // Release our reference; this is equivalent to 'delete this'
00604     // from the point of view of our thread.
00605     Release();
00606 }
00607 
00608 
00609 // *** ThreadList - used to tack all created threads
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     // Track the root thread that created us.
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         // Only original root thread can call this.
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         // Non-atomic creation ok since only the root thread
00666         if (!pRunningThreads)
00667         {
00668             pRunningThreads = new ThreadList;
00669             OVR_ASSERT(pRunningThreads);
00670         }
00671         pRunningThreads->addThread(pthread);
00672     }
00673 
00674     // NOTE: 'pthread' might be a dead pointer when this is
00675     // called so it should not be accessed; it is only used
00676     // for removal.
00677     static void RemoveRunningThread(Thread *pthread)
00678     {
00679         OVR_ASSERT(pRunningThreads);        
00680         pRunningThreads->removeThread(pthread);
00681     }
00682 
00683     static void FinishAllThreads()
00684     {
00685         // This is ok because only root thread can wait for other thread finish.
00686         if (pRunningThreads)
00687         {           
00688             pRunningThreads->finishAllThreads();
00689             delete pRunningThreads;
00690             pRunningThreads = 0;
00691         }        
00692     }
00693 };
00694 
00695 // By default, we have no thread list.
00696 ThreadList* volatile ThreadList::pRunningThreads = 0;
00697 
00698 
00699 // FinishAllThreads - exposed publicly in Thread.
00700 void Thread::FinishAllThreads()
00701 {
00702     ThreadList::FinishAllThreads();
00703 }
00704 
00705 
00706 // *** Run override
00707 
00708 int Thread::PRun()
00709 {
00710     // Suspend us on start, if requested
00711     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
00712     {
00713         Suspend();
00714         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
00715     }
00716 
00717     // Call the virtual run function
00718     ExitCode = Run();    
00719     return ExitCode;
00720 }
00721 
00722 
00723 
00724 /* MA: Don't use TLS for now.
00725 
00726 // Static function to return a pointer to the current thread
00727 void    Thread::InitCurrentThread(Thread *pthread)
00728 {
00729     pCurrentThread = pthread;
00730 }
00731 
00732 // Static function to return a pointer to the current thread
00733 Thread*    Thread::GetThread()
00734 {
00735     return pCurrentThread;
00736 }
00737 */
00738 
00739 
00740 // *** User overridables
00741 
00742 bool    Thread::GetExitFlag() const
00743 {
00744     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
00745 }       
00746 
00747 void    Thread::SetExitFlag(bool exitFlag)
00748 {
00749     // The below is atomic since ThreadFlags is AtomicInt.
00750     if (exitFlag)
00751         ThreadFlags |= OVR_THREAD_EXIT;
00752     else
00753         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
00754 }
00755 
00756 
00757 // Determines whether the thread was running and is now finished
00758 bool    Thread::IsFinished() const
00759 {
00760     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
00761 }
00762 // Determines whether the thread is suspended
00763 bool    Thread::IsSuspended() const
00764 {   
00765     return SuspendCount > 0;
00766 }
00767 // Returns current thread state
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 // ***** Thread management
00780 /* static */
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 // The actual first function called on thread start
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     // Ensure that ThreadId is assigned once thread is running, in case
00812     // beginthread hasn't filled it in yet.
00813     pthread->IdValue = (ThreadId)::GetCurrentThreadId();
00814 
00815     DWORD       result = pthread->PRun();
00816     // Signal the thread as done and release it atomically.
00817     pthread->FinishAndRelease();
00818     // At this point Thread object might be dead; however we can still pass
00819     // it to RemoveRunningThread since it is only used as a key there.    
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     // Free old thread handle before creating the new one
00835     CleanupSystemThread();
00836 
00837     // AddRef to us until the thread is finished.
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     // Failed? Fail the function
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 // Suspend the thread until resumed
00860 bool Thread::Suspend()
00861 {
00862     // Can't suspend a thread that wasn't started
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 // Resumes currently suspended thread
00875 bool Thread::Resume()
00876 {
00877     // Can't suspend a thread that wasn't started
00878     if (!(ThreadFlags & OVR_THREAD_STARTED))
00879         return 0;
00880 
00881     // Decrement count, and resume thread if it is 0
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 // Quits with an exit code  
00900 void Thread::Exit(int exitCode)
00901 {
00902     // Can only exist the current thread.
00903     // MA: Don't use TLS for now.
00904     //if (GetThread() != this)
00905     //    return;
00906 
00907     // Call the virtual OnExit function.
00908     OnExit();   
00909 
00910     // Signal this thread object as done and release it's references.
00911     FinishAndRelease();
00912     ThreadList::RemoveRunningThread(this);
00913 
00914     // Call the exit function.    
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 // *** Sleep functions
00929 // static
00930 bool Thread::Sleep(unsigned secs)
00931 {
00932     ::Sleep(secs*1000);
00933     return 1;
00934 }
00935 
00936 // static
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     // Looks ugly, but it is the recommended way to name a thread.
00947     typedef struct tagTHREADNAME_INFO {
00948         DWORD dwType;     // Must be 0x1000
00949         LPCSTR szName;    // Pointer to name (in user address space)
00950         DWORD dwThreadID; // Thread ID (-1 for caller thread)
00951         DWORD dwFlags;    // Reserved for future use; must be zero
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 // static
00976 int  Thread::GetCPUCount()
00977 {
00978     SYSTEM_INFO sysInfo;
00979     GetSystemInfo(&sysInfo);
00980     return (int) sysInfo.dwNumberOfProcessors;
00981 }
00982 
00983 // Returns the unique Id of a thread it is called on, intended for
00984 // comparison purposes.
00985 ThreadId GetCurrentThreadId()
00986 {
00987     return (ThreadId)::GetCurrentThreadId();
00988 }
00989 
00990 } // OVR
00991 
00992 #endif
00993 
00994 


oculus_sdk
Author(s): Tully Foote
autogenerated on Thu Jun 6 2019 20:13:48