oculus1

diff libovr/Src/win32/OVR_ThreadsWinAPI.cpp @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libovr/Src/win32/OVR_ThreadsWinAPI.cpp	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,1 @@
     1.4 +/************************************************************************************
     1.5 
     1.6 Filename    :   OVR_ThreadsWinAPI.cpp
     1.7 Platform    :   WinAPI
     1.8 Content     :   Windows specific thread-related (safe) functionality
     1.9 Created     :   September 19, 2012
    1.10 Notes       : 
    1.11 
    1.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    1.13 
    1.14 Use of this software is subject to the terms of the Oculus license
    1.15 agreement provided at the time of installation or download, or which
    1.16 otherwise accompanies this software in either electronic or hard copy form.
    1.17 
    1.18 ************************************************************************************/
    1.19 
    1.20 #include "OVR_Threads.h"
    1.21 #include "OVR_Hash.h"
    1.22 #include "OVR_Log.h"
    1.23 
    1.24 #ifdef OVR_ENABLE_THREADS
    1.25 
    1.26 // For _beginthreadex / _endtheadex
    1.27 #include <process.h>
    1.28 
    1.29 namespace OVR {
    1.30 
    1.31 
    1.32 //-----------------------------------------------------------------------------------
    1.33 // *** Internal Mutex implementation class
    1.34 
    1.35 class MutexImpl : public NewOverrideBase
    1.36 {
    1.37     // System mutex or semaphore
    1.38     HANDLE            hMutexOrSemaphore;
    1.39     bool              Recursive;
    1.40     volatile unsigned LockCount;
    1.41     
    1.42     friend class WaitConditionImpl;
    1.43 
    1.44 public:
    1.45     // Constructor/destructor
    1.46     MutexImpl(bool recursive = 1);
    1.47     ~MutexImpl();
    1.48 
    1.49     // Locking functions
    1.50     void                DoLock();
    1.51     bool                TryLock();
    1.52     void                Unlock(Mutex* pmutex);
    1.53     // Returns 1 if the mutes is currently locked
    1.54     bool                IsLockedByAnotherThread(Mutex* pmutex);
    1.55 };
    1.56 
    1.57 // *** Constructor/destructor
    1.58 MutexImpl::MutexImpl(bool recursive)
    1.59 {    
    1.60     Recursive                   = recursive;
    1.61     LockCount                   = 0;
    1.62     hMutexOrSemaphore           = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL);
    1.63 }
    1.64 MutexImpl::~MutexImpl()
    1.65 {
    1.66     CloseHandle(hMutexOrSemaphore);
    1.67 }
    1.68 
    1.69 
    1.70 // Lock and try lock
    1.71 void MutexImpl::DoLock()
    1.72 {
    1.73     if (::WaitForSingleObject(hMutexOrSemaphore, INFINITE) != WAIT_OBJECT_0)
    1.74         return;
    1.75     LockCount++;
    1.76 }
    1.77 
    1.78 bool MutexImpl::TryLock()
    1.79 {
    1.80     DWORD ret;
    1.81     if ((ret=::WaitForSingleObject(hMutexOrSemaphore, 0)) != WAIT_OBJECT_0)
    1.82         return 0;
    1.83     LockCount++;
    1.84     return 1;
    1.85 }
    1.86 
    1.87 void MutexImpl::Unlock(Mutex* pmutex)
    1.88 {
    1.89     OVR_UNUSED(pmutex);
    1.90 
    1.91     unsigned lockCount;
    1.92     LockCount--;
    1.93     lockCount = LockCount;
    1.94 
    1.95     // Release mutex
    1.96     if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) :
    1.97                      ReleaseSemaphore(hMutexOrSemaphore, 1, NULL))  != 0)
    1.98     {
    1.99         // This used to call Wait handlers if lockCount == 0.
   1.100     }
   1.101 }
   1.102 
   1.103 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
   1.104 {
   1.105     // There could be multiple interpretations of IsLocked with respect to current thread
   1.106     if (LockCount == 0)
   1.107         return 0;
   1.108     if (!TryLock())
   1.109         return 1;
   1.110     Unlock(pmutex);
   1.111     return 0;
   1.112 }
   1.113 
   1.114 /*
   1.115 bool    MutexImpl::IsSignaled() const
   1.116 {
   1.117     // An mutex is signaled if it is not locked ANYWHERE
   1.118     // Note that this is different from IsLockedByAnotherThread function,
   1.119     // that takes current thread into account
   1.120     return LockCount == 0;
   1.121 }
   1.122 */
   1.123 
   1.124 
   1.125 // *** Actual Mutex class implementation
   1.126 
   1.127 Mutex::Mutex(bool recursive)
   1.128 {    
   1.129     pImpl = new MutexImpl(recursive);
   1.130 }
   1.131 Mutex::~Mutex()
   1.132 {
   1.133     delete pImpl;
   1.134 }
   1.135 
   1.136 // Lock and try lock
   1.137 void Mutex::DoLock()
   1.138 {
   1.139     pImpl->DoLock();
   1.140 }
   1.141 bool Mutex::TryLock()
   1.142 {
   1.143     return pImpl->TryLock();
   1.144 }
   1.145 void Mutex::Unlock()
   1.146 {
   1.147     pImpl->Unlock(this);
   1.148 }
   1.149 bool Mutex::IsLockedByAnotherThread()
   1.150 {
   1.151     return pImpl->IsLockedByAnotherThread(this);
   1.152 }
   1.153 
   1.154 //-----------------------------------------------------------------------------------
   1.155 // ***** Event
   1.156 
   1.157 bool Event::Wait(unsigned delay)
   1.158 {
   1.159     Mutex::Locker lock(&StateMutex);
   1.160 
   1.161     // Do the correct amount of waiting
   1.162     if (delay == OVR_WAIT_INFINITE)
   1.163     {
   1.164         while(!State)
   1.165             StateWaitCondition.Wait(&StateMutex);
   1.166     }
   1.167     else if (delay)
   1.168     {
   1.169         if (!State)
   1.170             StateWaitCondition.Wait(&StateMutex, delay);
   1.171     }
   1.172 
   1.173     bool state = State;
   1.174     // Take care of temporary 'pulsing' of a state
   1.175     if (Temporary)
   1.176     {
   1.177         Temporary   = false;
   1.178         State       = false;
   1.179     }
   1.180     return state;
   1.181 }
   1.182 
   1.183 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
   1.184 {
   1.185     Mutex::Locker lock(&StateMutex);
   1.186     State       = newState;
   1.187     Temporary   = newTemp;
   1.188     if (mustNotify)
   1.189         StateWaitCondition.NotifyAll();    
   1.190 }
   1.191 
   1.192 
   1.193 //-----------------------------------------------------------------------------------
   1.194 // ***** Win32 Wait Condition Implementation
   1.195 
   1.196 // Internal implementation class
   1.197 class WaitConditionImpl : public NewOverrideBase
   1.198 {   
   1.199     // Event pool entries for extra events
   1.200     struct EventPoolEntry  : public NewOverrideBase
   1.201     {
   1.202         HANDLE          hEvent;
   1.203         EventPoolEntry  *pNext;
   1.204         EventPoolEntry  *pPrev;
   1.205     };
   1.206     
   1.207     Lock                WaitQueueLoc;
   1.208     // Stores free events that can be used later
   1.209     EventPoolEntry  *   pFreeEventList;
   1.210     
   1.211     // A queue of waiting objects to be signaled    
   1.212     EventPoolEntry*     pQueueHead;
   1.213     EventPoolEntry*     pQueueTail;
   1.214 
   1.215     // Allocation functions for free events
   1.216     EventPoolEntry*     GetNewEvent();
   1.217     void                ReleaseEvent(EventPoolEntry* pevent);
   1.218 
   1.219     // Queue operations
   1.220     void                QueuePush(EventPoolEntry* pentry);
   1.221     EventPoolEntry*     QueuePop();
   1.222     void                QueueFindAndRemove(EventPoolEntry* pentry);
   1.223 
   1.224 public:
   1.225 
   1.226     // Constructor/destructor
   1.227     WaitConditionImpl();
   1.228     ~WaitConditionImpl();
   1.229 
   1.230     // Release mutex and wait for condition. The mutex is re-acqured after the wait.
   1.231     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
   1.232 
   1.233     // Notify a condition, releasing at one object waiting
   1.234     void    Notify();
   1.235     // Notify a condition, releasing all objects waiting
   1.236     void    NotifyAll();
   1.237 };
   1.238 
   1.239 
   1.240 
   1.241 WaitConditionImpl::WaitConditionImpl()
   1.242 {
   1.243     pFreeEventList  = 0;
   1.244     pQueueHead      =
   1.245     pQueueTail      = 0;
   1.246 }
   1.247 
   1.248 WaitConditionImpl::~WaitConditionImpl()
   1.249 {
   1.250     // Free all the resources
   1.251     EventPoolEntry* p       = pFreeEventList;
   1.252     EventPoolEntry* pentry;
   1.253 
   1.254     while(p)
   1.255     {
   1.256         // Move to next
   1.257         pentry = p;
   1.258         p = p->pNext;
   1.259         // Delete old
   1.260         ::CloseHandle(pentry->hEvent);
   1.261         delete pentry;  
   1.262     }   
   1.263     // Shouldn't we also consider the queue?
   1.264 
   1.265     // To be safe
   1.266     pFreeEventList  = 0;
   1.267     pQueueHead      =
   1.268     pQueueTail      = 0;
   1.269 }
   1.270 
   1.271 
   1.272 // Allocation functions for free events
   1.273 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent()
   1.274 {
   1.275     EventPoolEntry* pentry;
   1.276 
   1.277     // If there are any free nodes, use them
   1.278     if (pFreeEventList)
   1.279     {
   1.280         pentry          = pFreeEventList;
   1.281         pFreeEventList  = pFreeEventList->pNext;        
   1.282     }
   1.283     else
   1.284     {
   1.285         // Allocate a new node
   1.286         pentry          = new EventPoolEntry;
   1.287         pentry->pNext   = 0;
   1.288         pentry->pPrev   = 0;
   1.289         // Non-signaled manual event
   1.290         pentry->hEvent  = ::CreateEvent(NULL, TRUE, 0, NULL);
   1.291     }
   1.292     
   1.293     return pentry;
   1.294 }
   1.295 
   1.296 void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent)
   1.297 {
   1.298     // Mark event as non-signaled
   1.299     ::ResetEvent(pevent->hEvent);
   1.300     // And add it to free pool
   1.301     pevent->pNext   = pFreeEventList;
   1.302     pevent->pPrev   = 0;
   1.303     pFreeEventList  = pevent;
   1.304 }
   1.305 
   1.306 // Queue operations
   1.307 void WaitConditionImpl::QueuePush(EventPoolEntry* pentry)
   1.308 {
   1.309     // Items already exist? Just add to tail
   1.310     if (pQueueTail)
   1.311     {
   1.312         pentry->pPrev       = pQueueTail;
   1.313         pQueueTail->pNext   = pentry;
   1.314         pentry->pNext       = 0;        
   1.315         pQueueTail          = pentry;       
   1.316     }
   1.317     else
   1.318     {
   1.319         // No items in queue
   1.320         pentry->pNext   = 
   1.321         pentry->pPrev   = 0;
   1.322         pQueueHead      =
   1.323         pQueueTail      = pentry;
   1.324     }
   1.325 }
   1.326 
   1.327 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::QueuePop()
   1.328 {
   1.329     EventPoolEntry* pentry = pQueueHead;
   1.330 
   1.331     // No items, null pointer
   1.332     if (pentry)
   1.333     {
   1.334         // More items after this one? just grab the first item
   1.335         if (pQueueHead->pNext)
   1.336         {       
   1.337             pQueueHead  = pentry->pNext;
   1.338             pQueueHead->pPrev = 0;      
   1.339         }
   1.340         else
   1.341         {
   1.342             // Last item left
   1.343             pQueueTail =
   1.344             pQueueHead = 0;
   1.345         }
   1.346     }   
   1.347     return pentry;
   1.348 }
   1.349 
   1.350 void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry)
   1.351 {
   1.352     // Do an exhaustive search looking for an entry
   1.353     EventPoolEntry* p = pQueueHead;
   1.354 
   1.355     while(p)
   1.356     {
   1.357         // Entry found? Remove.
   1.358         if (p == pentry)
   1.359         {
   1.360             
   1.361             // Remove the node form the list
   1.362             // Prev link
   1.363             if (pentry->pPrev)
   1.364                 pentry->pPrev->pNext = pentry->pNext;
   1.365             else
   1.366                 pQueueHead = pentry->pNext;
   1.367             // Next link
   1.368             if (pentry->pNext)
   1.369                 pentry->pNext->pPrev = pentry->pPrev;
   1.370             else
   1.371                 pQueueTail = pentry->pPrev;
   1.372             // Done
   1.373             return;
   1.374         }
   1.375 
   1.376         // Move to next item
   1.377         p = p->pNext;
   1.378     }
   1.379 }
   1.380     
   1.381 
   1.382 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
   1.383 {
   1.384     bool            result = 0;
   1.385     unsigned        i;
   1.386     unsigned        lockCount = pmutex->pImpl->LockCount;
   1.387     EventPoolEntry* pentry;
   1.388 
   1.389     // Mutex must have been locked
   1.390     if (lockCount == 0)
   1.391         return 0;
   1.392     
   1.393     // Add an object to the wait queue
   1.394     WaitQueueLoc.DoLock();
   1.395     QueuePush(pentry = GetNewEvent());
   1.396     WaitQueueLoc.Unlock();
   1.397 
   1.398     // Finally, release a mutex or semaphore
   1.399     if (pmutex->pImpl->Recursive)
   1.400     {
   1.401         // Release the recursive mutex N times
   1.402         pmutex->pImpl->LockCount = 0;
   1.403         for(i=0; i<lockCount; i++)
   1.404             ::ReleaseMutex(pmutex->pImpl->hMutexOrSemaphore);
   1.405     }
   1.406     else
   1.407     {
   1.408         pmutex->pImpl->LockCount = 0;
   1.409         ::ReleaseSemaphore(pmutex->pImpl->hMutexOrSemaphore, 1, NULL);
   1.410     }
   1.411 
   1.412     // Note that there is a gap here between mutex.Unlock() and Wait(). However,
   1.413     // if notify() comes in at this point in the other thread it will set our
   1.414     // corresponding event so wait will just fall through, as expected.
   1.415 
   1.416     // Block and wait on the event
   1.417     DWORD waitResult = ::WaitForSingleObject(pentry->hEvent,
   1.418                             (delay == OVR_WAIT_INFINITE) ? INFINITE : delay);
   1.419     /*
   1.420 repeat_wait:
   1.421     DWORD waitResult =
   1.422 
   1.423     ::MsgWaitForMultipleObjects(1, &pentry->hEvent, FALSE,
   1.424                                 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay,
   1.425                                 QS_ALLINPUT);
   1.426     */
   1.427 
   1.428     WaitQueueLoc.DoLock();
   1.429     switch(waitResult)
   1.430     {
   1.431         case WAIT_ABANDONED:
   1.432         case WAIT_OBJECT_0: 
   1.433             result = 1;
   1.434             // Wait was successful, therefore the event entry should already be removed
   1.435             // So just add entry back to a free list
   1.436             ReleaseEvent(pentry);
   1.437             break;
   1.438             /*
   1.439         case WAIT_OBJECT_0 + 1:
   1.440             // Messages in WINDOWS queue
   1.441             {
   1.442                 MSG msg;
   1.443                 PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);             
   1.444                 WaitQueueLoc.Unlock();
   1.445                 goto repeat_wait;
   1.446             }
   1.447             break; */
   1.448         default:
   1.449             // Timeout, our entry should still be in a queue
   1.450             QueueFindAndRemove(pentry);
   1.451             ReleaseEvent(pentry);
   1.452     }
   1.453     WaitQueueLoc.Unlock();
   1.454 
   1.455     // Re-aquire the mutex
   1.456     for(i=0; i<lockCount; i++)
   1.457         pmutex->DoLock(); 
   1.458 
   1.459     // Return the result
   1.460     return result;
   1.461 }
   1.462 
   1.463 // Notify a condition, releasing the least object in a queue
   1.464 void WaitConditionImpl::Notify()
   1.465 {
   1.466     Lock::Locker   lock(&WaitQueueLoc);
   1.467     
   1.468     // Pop last entry & signal it
   1.469     EventPoolEntry* pentry = QueuePop();    
   1.470     if (pentry)
   1.471         ::SetEvent(pentry->hEvent); 
   1.472 }
   1.473 
   1.474 // Notify a condition, releasing all objects waiting
   1.475 void WaitConditionImpl::NotifyAll()
   1.476 {
   1.477     Lock::Locker   lock(&WaitQueueLoc);
   1.478 
   1.479     // Pop and signal all events
   1.480     // NOTE : There is no need to release the events, it's the waiters job to do so 
   1.481     EventPoolEntry* pentry = QueuePop();
   1.482     while (pentry)
   1.483     {
   1.484         ::SetEvent(pentry->hEvent);
   1.485         pentry = QueuePop();
   1.486     }
   1.487 }
   1.488 
   1.489 
   1.490 
   1.491 // *** Actual implementation of WaitCondition
   1.492 
   1.493 WaitCondition::WaitCondition()
   1.494 {
   1.495     pImpl = new WaitConditionImpl;
   1.496 }
   1.497 WaitCondition::~WaitCondition()
   1.498 {
   1.499     delete pImpl;
   1.500 }
   1.501     
   1.502 // Wait without a mutex
   1.503 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
   1.504 {
   1.505     return pImpl->Wait(pmutex, delay);
   1.506 }
   1.507 // Notification
   1.508 void    WaitCondition::Notify()
   1.509 {
   1.510     pImpl->Notify();
   1.511 }
   1.512 void    WaitCondition::NotifyAll()
   1.513 {
   1.514     pImpl->NotifyAll();
   1.515 }
   1.516 
   1.517 
   1.518 
   1.519 //-----------------------------------------------------------------------------------
   1.520 // ***** Thread Class
   1.521 
   1.522 //  Per-thread variable
   1.523 //  MA: Don't use TLS for now - portability issues with DLLs, etc.
   1.524 /*
   1.525 #if !defined(OVR_CC_MSVC) || (OVR_CC_MSVC < 1300)
   1.526 __declspec(thread)  Thread*    pCurrentThread      = 0;
   1.527 #else
   1.528 #pragma data_seg(".tls$")
   1.529 __declspec(thread)  Thread*    pCurrentThread      = 0;
   1.530 #pragma data_seg(".rwdata")
   1.531 #endif
   1.532 */
   1.533 
   1.534 // *** Thread constructors.
   1.535 
   1.536 Thread::Thread(UPInt stackSize, int processor)
   1.537 {    
   1.538     CreateParams params;
   1.539     params.stackSize = stackSize;
   1.540     params.processor = processor;
   1.541     Init(params);
   1.542 }
   1.543 
   1.544 Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize, 
   1.545                  int processor, Thread::ThreadState initialState)
   1.546 {
   1.547     CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
   1.548     Init(params);
   1.549 }
   1.550 
   1.551 Thread::Thread(const CreateParams& params)
   1.552 {
   1.553     Init(params);
   1.554 }
   1.555 void Thread::Init(const CreateParams& params)
   1.556 {
   1.557     // Clear the variables    
   1.558     ThreadFlags     = 0;
   1.559     ThreadHandle    = 0;
   1.560     IdValue         = 0;
   1.561     ExitCode        = 0;
   1.562     SuspendCount    = 0;
   1.563     StackSize       = params.stackSize;
   1.564     Processor       = params.processor;
   1.565     Priority        = params.priority;
   1.566 
   1.567     // Clear Function pointers
   1.568     ThreadFunction  = params.threadFunction;
   1.569     UserHandle      = params.userHandle;
   1.570     if (params.initialState != NotRunning)
   1.571         Start(params.initialState);
   1.572 
   1.573 }
   1.574 
   1.575 Thread::~Thread()
   1.576 {
   1.577     // Thread should not running while object is being destroyed,
   1.578     // this would indicate ref-counting issue.
   1.579     //OVR_ASSERT(IsRunning() == 0);
   1.580   
   1.581     // Clean up thread.    
   1.582     CleanupSystemThread();
   1.583     ThreadHandle = 0;
   1.584 }
   1.585 
   1.586 
   1.587 // *** Overridable User functions.
   1.588 
   1.589 // Default Run implementation
   1.590 int Thread::Run()
   1.591 {
   1.592     // Call pointer to function, if available.    
   1.593     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
   1.594 }
   1.595 void Thread::OnExit()
   1.596 {   
   1.597 }
   1.598 
   1.599 // Finishes the thread and releases internal reference to it.
   1.600 void Thread::FinishAndRelease()
   1.601 {
   1.602     // Note: thread must be US.
   1.603     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
   1.604     ThreadFlags |= OVR_THREAD_FINISHED;
   1.605 
   1.606     // Release our reference; this is equivalent to 'delete this'
   1.607     // from the point of view of our thread.
   1.608     Release();
   1.609 }
   1.610 
   1.611 
   1.612 // *** ThreadList - used to tack all created threads
   1.613 
   1.614 class ThreadList : public NewOverrideBase
   1.615 {
   1.616     //------------------------------------------------------------------------
   1.617     struct ThreadHashOp
   1.618     {
   1.619         UPInt operator()(const Thread* ptr)
   1.620         {
   1.621             return (((UPInt)ptr) >> 6) ^ (UPInt)ptr;
   1.622         }
   1.623     };
   1.624 
   1.625     HashSet<Thread*, ThreadHashOp>  ThreadSet;
   1.626     Mutex                           ThreadMutex;
   1.627     WaitCondition                   ThreadsEmpty;
   1.628     // Track the root thread that created us.
   1.629     ThreadId                        RootThreadId;
   1.630 
   1.631     static ThreadList* volatile pRunningThreads;
   1.632 
   1.633     void addThread(Thread *pthread)
   1.634     {
   1.635          Mutex::Locker lock(&ThreadMutex);
   1.636          ThreadSet.Add(pthread);
   1.637     }
   1.638 
   1.639     void removeThread(Thread *pthread)
   1.640     {
   1.641         Mutex::Locker lock(&ThreadMutex);
   1.642         ThreadSet.Remove(pthread);
   1.643         if (ThreadSet.GetSize() == 0)
   1.644             ThreadsEmpty.Notify();
   1.645     }
   1.646 
   1.647     void finishAllThreads()
   1.648     {
   1.649         // Only original root thread can call this.
   1.650         OVR_ASSERT(GetCurrentThreadId() == RootThreadId);
   1.651 
   1.652         Mutex::Locker lock(&ThreadMutex);
   1.653         while (ThreadSet.GetSize() != 0)
   1.654             ThreadsEmpty.Wait(&ThreadMutex);
   1.655     }
   1.656 
   1.657 public:
   1.658 
   1.659     ThreadList()
   1.660     {
   1.661         RootThreadId = GetCurrentThreadId();
   1.662     }
   1.663     ~ThreadList() { }
   1.664 
   1.665 
   1.666     static void AddRunningThread(Thread *pthread)
   1.667     {
   1.668         // Non-atomic creation ok since only the root thread
   1.669         if (!pRunningThreads)
   1.670         {
   1.671             pRunningThreads = new ThreadList;
   1.672             OVR_ASSERT(pRunningThreads);
   1.673         }
   1.674         pRunningThreads->addThread(pthread);
   1.675     }
   1.676 
   1.677     // NOTE: 'pthread' might be a dead pointer when this is
   1.678     // called so it should not be accessed; it is only used
   1.679     // for removal.
   1.680     static void RemoveRunningThread(Thread *pthread)
   1.681     {
   1.682         OVR_ASSERT(pRunningThreads);        
   1.683         pRunningThreads->removeThread(pthread);
   1.684     }
   1.685 
   1.686     static void FinishAllThreads()
   1.687     {
   1.688         // This is ok because only root thread can wait for other thread finish.
   1.689         if (pRunningThreads)
   1.690         {           
   1.691             pRunningThreads->finishAllThreads();
   1.692             delete pRunningThreads;
   1.693             pRunningThreads = 0;
   1.694         }        
   1.695     }
   1.696 };
   1.697 
   1.698 // By default, we have no thread list.
   1.699 ThreadList* volatile ThreadList::pRunningThreads = 0;
   1.700 
   1.701 
   1.702 // FinishAllThreads - exposed publicly in Thread.
   1.703 void Thread::FinishAllThreads()
   1.704 {
   1.705     ThreadList::FinishAllThreads();
   1.706 }
   1.707 
   1.708 
   1.709 // *** Run override
   1.710 
   1.711 int Thread::PRun()
   1.712 {
   1.713     // Suspend us on start, if requested
   1.714     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
   1.715     {
   1.716         Suspend();
   1.717         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
   1.718     }
   1.719 
   1.720     // Call the virtual run function
   1.721     ExitCode = Run();    
   1.722     return ExitCode;
   1.723 }
   1.724 
   1.725 
   1.726 
   1.727 /* MA: Don't use TLS for now.
   1.728 
   1.729 // Static function to return a pointer to the current thread
   1.730 void    Thread::InitCurrentThread(Thread *pthread)
   1.731 {
   1.732     pCurrentThread = pthread;
   1.733 }
   1.734 
   1.735 // Static function to return a pointer to the current thread
   1.736 Thread*    Thread::GetThread()
   1.737 {
   1.738     return pCurrentThread;
   1.739 }
   1.740 */
   1.741 
   1.742 
   1.743 // *** User overridables
   1.744 
   1.745 bool    Thread::GetExitFlag() const
   1.746 {
   1.747     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
   1.748 }       
   1.749 
   1.750 void    Thread::SetExitFlag(bool exitFlag)
   1.751 {
   1.752     // The below is atomic since ThreadFlags is AtomicInt.
   1.753     if (exitFlag)
   1.754         ThreadFlags |= OVR_THREAD_EXIT;
   1.755     else
   1.756         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
   1.757 }
   1.758 
   1.759 
   1.760 // Determines whether the thread was running and is now finished
   1.761 bool    Thread::IsFinished() const
   1.762 {
   1.763     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
   1.764 }
   1.765 // Determines whether the thread is suspended
   1.766 bool    Thread::IsSuspended() const
   1.767 {   
   1.768     return SuspendCount > 0;
   1.769 }
   1.770 // Returns current thread state
   1.771 Thread::ThreadState Thread::GetThreadState() const
   1.772 {
   1.773     if (IsSuspended())
   1.774         return Suspended;    
   1.775     if (ThreadFlags & OVR_THREAD_STARTED)
   1.776         return Running;    
   1.777     return NotRunning;
   1.778 }
   1.779 
   1.780 
   1.781 
   1.782 // ***** Thread management
   1.783 /* static */
   1.784 int Thread::GetOSPriority(ThreadPriority p)
   1.785 {
   1.786     switch(p)
   1.787     {
   1.788     case Thread::CriticalPriority:      return THREAD_PRIORITY_TIME_CRITICAL;
   1.789     case Thread::HighestPriority:       return THREAD_PRIORITY_HIGHEST;
   1.790     case Thread::AboveNormalPriority:   return THREAD_PRIORITY_ABOVE_NORMAL;
   1.791     case Thread::NormalPriority:        return THREAD_PRIORITY_NORMAL;
   1.792     case Thread::BelowNormalPriority:   return THREAD_PRIORITY_BELOW_NORMAL;
   1.793     case Thread::LowestPriority:        return THREAD_PRIORITY_LOWEST;
   1.794     case Thread::IdlePriority:          return THREAD_PRIORITY_IDLE;
   1.795     }
   1.796     return THREAD_PRIORITY_NORMAL;
   1.797 }
   1.798 
   1.799 // The actual first function called on thread start
   1.800 unsigned WINAPI Thread_Win32StartFn(void * phandle)
   1.801 {
   1.802     Thread *   pthread = (Thread*)phandle;
   1.803     if (pthread->Processor != -1)
   1.804     {
   1.805         DWORD_PTR ret = SetThreadAffinityMask(GetCurrentThread(), (DWORD)pthread->Processor);
   1.806         if (ret == 0)
   1.807             OVR_DEBUG_LOG(("Could not set hardware processor for the thread"));
   1.808     }
   1.809     BOOL ret = ::SetThreadPriority(GetCurrentThread(), Thread::GetOSPriority(pthread->Priority));
   1.810     if (ret == 0)
   1.811         OVR_DEBUG_LOG(("Could not set thread priority"));
   1.812     OVR_UNUSED(ret);
   1.813 
   1.814     // Ensure that ThreadId is assigned once thread is running, in case
   1.815     // beginthread hasn't filled it in yet.
   1.816     pthread->IdValue = (ThreadId)::GetCurrentThreadId();
   1.817 
   1.818     DWORD       result = pthread->PRun();
   1.819     // Signal the thread as done and release it atomically.
   1.820     pthread->FinishAndRelease();
   1.821     // At this point Thread object might be dead; however we can still pass
   1.822     // it to RemoveRunningThread since it is only used as a key there.    
   1.823     ThreadList::RemoveRunningThread(pthread);
   1.824     return (unsigned) result;
   1.825 }
   1.826 
   1.827 bool Thread::Start(ThreadState initialState)
   1.828 {
   1.829     if (initialState == NotRunning)
   1.830         return 0;
   1.831     if (GetThreadState() != NotRunning)
   1.832     {
   1.833         OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
   1.834         return 0;
   1.835     }
   1.836 
   1.837     // Free old thread handle before creating the new one
   1.838     CleanupSystemThread();
   1.839 
   1.840     // AddRef to us until the thread is finished.
   1.841     AddRef();
   1.842     ThreadList::AddRunningThread(this);
   1.843     
   1.844     ExitCode        = 0;
   1.845     SuspendCount    = 0;
   1.846     ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
   1.847     ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize,
   1.848                                            Thread_Win32StartFn, this, 0, (unsigned*)&IdValue);
   1.849 
   1.850     // Failed? Fail the function
   1.851     if (ThreadHandle == 0)
   1.852     {
   1.853         ThreadFlags = 0;
   1.854         Release();
   1.855         ThreadList::RemoveRunningThread(this);
   1.856         return 0;
   1.857     }
   1.858     return 1;
   1.859 }
   1.860 
   1.861 
   1.862 // Suspend the thread until resumed
   1.863 bool Thread::Suspend()
   1.864 {
   1.865     // Can't suspend a thread that wasn't started
   1.866     if (!(ThreadFlags & OVR_THREAD_STARTED))
   1.867         return 0;
   1.868 
   1.869     if (::SuspendThread(ThreadHandle) != 0xFFFFFFFF)
   1.870     {        
   1.871         SuspendCount++;        
   1.872         return 1;
   1.873     }
   1.874     return 0;
   1.875 }
   1.876 
   1.877 // Resumes currently suspended thread
   1.878 bool Thread::Resume()
   1.879 {
   1.880     // Can't suspend a thread that wasn't started
   1.881     if (!(ThreadFlags & OVR_THREAD_STARTED))
   1.882         return 0;
   1.883 
   1.884     // Decrement count, and resume thread if it is 0
   1.885     SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1);
   1.886     if (oldCount >= 1)
   1.887     {
   1.888         if (oldCount == 1)
   1.889         {
   1.890             if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF)            
   1.891                 return 1;            
   1.892         }
   1.893         else
   1.894         {
   1.895             return 1;
   1.896         }
   1.897     }   
   1.898     return 0;
   1.899 }
   1.900 
   1.901 
   1.902 // Quits with an exit code  
   1.903 void Thread::Exit(int exitCode)
   1.904 {
   1.905     // Can only exist the current thread.
   1.906     // MA: Don't use TLS for now.
   1.907     //if (GetThread() != this)
   1.908     //    return;
   1.909 
   1.910     // Call the virtual OnExit function.
   1.911     OnExit();   
   1.912 
   1.913     // Signal this thread object as done and release it's references.
   1.914     FinishAndRelease();
   1.915     ThreadList::RemoveRunningThread(this);
   1.916 
   1.917     // Call the exit function.    
   1.918     _endthreadex((unsigned)exitCode);
   1.919 }
   1.920 
   1.921 
   1.922 void Thread::CleanupSystemThread()
   1.923 {
   1.924     if (ThreadHandle != 0)
   1.925     {
   1.926         ::CloseHandle(ThreadHandle);
   1.927         ThreadHandle = 0;
   1.928     }
   1.929 }
   1.930 
   1.931 // *** Sleep functions
   1.932 // static
   1.933 bool Thread::Sleep(unsigned secs)
   1.934 {
   1.935     ::Sleep(secs*1000);
   1.936     return 1;
   1.937 }
   1.938 
   1.939 // static
   1.940 bool Thread::MSleep(unsigned msecs)
   1.941 {
   1.942     ::Sleep(msecs);
   1.943     return 1;
   1.944 }
   1.945 
   1.946 void Thread::SetThreadName( const char* name )
   1.947 {
   1.948 #if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING)
   1.949     // Looks ugly, but it is the recommended way to name a thread.
   1.950     typedef struct tagTHREADNAME_INFO {
   1.951         DWORD dwType;     // Must be 0x1000
   1.952         LPCSTR szName;    // Pointer to name (in user address space)
   1.953         DWORD dwThreadID; // Thread ID (-1 for caller thread)
   1.954         DWORD dwFlags;    // Reserved for future use; must be zero
   1.955     } THREADNAME_INFO;
   1.956 
   1.957     THREADNAME_INFO info;
   1.958 
   1.959     info.dwType = 0x1000;
   1.960     info.szName = name;
   1.961     info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId());
   1.962     info.dwFlags = 0;
   1.963 
   1.964     __try
   1.965     {
   1.966 #ifdef _WIN64
   1.967         RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info );
   1.968 #else
   1.969         RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info );
   1.970 #endif
   1.971     }
   1.972     __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER )
   1.973     {
   1.974     }
   1.975 #endif // OVR_BUILD_SHIPPING
   1.976 }
   1.977 
   1.978 // static
   1.979 int  Thread::GetCPUCount()
   1.980 {
   1.981     SYSTEM_INFO sysInfo;
   1.982     GetSystemInfo(&sysInfo);
   1.983     return (int) sysInfo.dwNumberOfProcessors;
   1.984 }
   1.985 
   1.986 // Returns the unique Id of a thread it is called on, intended for
   1.987 // comparison purposes.
   1.988 ThreadId GetCurrentThreadId()
   1.989 {
   1.990     return (ThreadId)::GetCurrentThreadId();
   1.991 }
   1.992 
   1.993 } // OVR
   1.994 
   1.995 #endif
   1.996 
   1.997 
   1.998 \ No newline at end of file