threads_win32.cpp

Go to the documentation of this file.
00001 #include <windows.h>
00002 #include <process.h>
00003 #include "threads.h"
00004 
00005 
00006 namespace audiere {
00007 
00008   struct ThreadInternal {
00009     AI_ThreadRoutine routine;
00010     void*            opaque;
00011   };
00012 
00013   static unsigned WINAPI InternalThreadRoutine(void* opaque);
00014 
00015 
00016   bool SupportsThreadPriority() {
00017     // For some reason or another, Windows 95, 98, and ME always
00018     // deadlock when Audiere tries to use a thread priority other
00019     // than 0.  Therefore, disable the higher priority on those
00020     // operating systems.
00021     OSVERSIONINFO info;
00022     info.dwOSVersionInfoSize = sizeof(info);
00023     if (GetVersionEx(&info) &&
00024         info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
00025       return false;
00026     } else {
00027       return true;
00028     }
00029   }
00030 
00031 
00032   int GetWin32Priority(int priority) {
00033     if (priority < -2) {
00034       return THREAD_PRIORITY_IDLE;
00035     } else if (priority == -2) {
00036       return THREAD_PRIORITY_LOWEST;
00037     } else if (priority == -1) {
00038       return THREAD_PRIORITY_BELOW_NORMAL;
00039     } else if (priority == 0) {
00040       return THREAD_PRIORITY_NORMAL;
00041     } else if (priority == 1) {
00042       return THREAD_PRIORITY_ABOVE_NORMAL;
00043     } else {
00044       return THREAD_PRIORITY_HIGHEST;
00045     }
00046   }
00047 
00048 
00049   bool AI_CreateThread(AI_ThreadRoutine routine, void* opaque, int priority) {
00050     // create internal thread data
00051     ThreadInternal* internal = new ThreadInternal;
00052     internal->routine  = routine;
00053     internal->opaque   = opaque;
00054     
00055     // create the actual thread
00056     unsigned threadid;
00057     HANDLE handle = (HANDLE)_beginthreadex(
00058       0, 0, InternalThreadRoutine, internal, CREATE_SUSPENDED, &threadid);
00059     if (handle) {
00060       if (SupportsThreadPriority()) {
00061         SetThreadPriority(handle, GetWin32Priority(priority));
00062       }
00063       ResumeThread(handle);
00064       CloseHandle(handle);
00065       return true;
00066     } else {
00067       return false;
00068     }
00069   }
00070 
00071 
00072   unsigned WINAPI InternalThreadRoutine(void* opaque) {
00073     ThreadInternal* internal = static_cast<ThreadInternal*>(opaque);
00074 
00075     // call the function passed 
00076     internal->routine(internal->opaque);
00077     delete internal;
00078     return 0;
00079   }
00080 
00081 
00082   void AI_Sleep(unsigned milliseconds) {
00083     ::Sleep(milliseconds);
00084   }
00085 
00086 
00087   struct Mutex::Impl {
00088     CRITICAL_SECTION cs;
00089   };
00090 
00091   Mutex::Mutex() {
00092     m_impl = new Impl;
00093     InitializeCriticalSection(&m_impl->cs);
00094   }
00095 
00096   Mutex::~Mutex() {
00097     DeleteCriticalSection(&m_impl->cs);
00098     delete m_impl;
00099   }
00100 
00101   void Mutex::lock() {
00102     EnterCriticalSection(&m_impl->cs);
00103   }
00104 
00105   void Mutex::unlock() {
00106     LeaveCriticalSection(&m_impl->cs);
00107   }
00108 
00109 
00110   // This probably isn't a safe way to implement a condition variable.  I suspect
00111   // wait() isn't totally thread-safe, i.e. multiple threads waiting on a cvar could
00112   // unlock the mutex at bad times.
00113 
00114   struct CondVar::Impl {
00115     HANDLE event;
00116   };
00117 
00118   CondVar::CondVar() {
00119     ADR_GUARD("CondVar::CondVar");
00120     m_impl = new Impl;
00121     m_impl->event = CreateEvent(0, FALSE, FALSE, 0);
00122     if (!m_impl->event) {
00123       ADR_LOG("CreateEvent() failed");
00124       abort();
00125     }
00126   }
00127 
00128   CondVar::~CondVar() {
00129     CloseHandle(m_impl->event);
00130     delete m_impl;
00131   }
00132 
00133   void CondVar::wait(Mutex& mutex, float seconds) {
00134     mutex.unlock();
00135     WaitForSingleObject(m_impl->event, int(seconds * 1000));
00136     mutex.lock();
00137   }
00138 
00139   void CondVar::notify() {
00140     SetEvent(m_impl->event);
00141   }
00142 
00143 }

Generated on Mon Feb 13 23:07:47 2006 for audiere by  doxygen 1.4.6