00001 #include "Synchronization.h"
00002
00003 #ifdef LINUX
00004 #include <pthread.h>
00005 #include <sys/timeb.h>
00006 #include <errno.h>
00007 #endif
00008 #include <assert.h>
00009 namespace rwil {
00010 #ifdef LINUX
00011 void *StartThread(void * threadObject)
00012 {
00013 Thread * thread = (Thread *)threadObject;
00014 thread->Go();
00015 return NULL;
00016 }
00017 #endif
00018
00019 Mutex::Mutex()
00020 {
00021 #ifdef _WIN32
00022 m_mutex = CreateMutex(NULL, TRUE, NULL);
00023 if(m_mutex = NULL)
00024 {
00025 throw "Unable to create mutex";
00026 }
00027 #endif
00028 #ifdef LINUX
00029
00030 pthread_mutexattr_t attr;
00031 pthread_mutexattr_init(&attr);
00032 attr.__mutexkind= PTHREAD_MUTEX_RECURSIVE_NP;
00033
00034 pthread_mutex_init(&m_mutex, &attr);
00035 #endif
00036 }
00037 Mutex::~Mutex()
00038 {
00039 #ifdef _WIN32
00040 CloseHandle(m_mutex);
00041 #endif
00042 #ifdef LINUX
00043
00044
00045 #endif
00046 }
00047 #ifdef LINUX
00048 void Mutex::Wait()
00049 {
00050 pthread_mutex_lock(&m_mutex);
00051 }
00052
00053 bool Mutex::TryWait()
00054 {
00055 return pthread_mutex_trylock(&m_mutex) == 0;
00056 }
00057
00058 void Mutex::Release()
00059 {
00060 pthread_mutex_unlock(&m_mutex);
00061 }
00062 #endif //LINUX
00063
00064 #ifdef _WIN32
00065 static bool WaitWithTimeout(int milli)
00066 {
00067
00068 DWORD dwRet = WaitForSingleObject(m_mutex, milli);
00069
00070 switch (dwWaitResult)
00071 {
00072 case WAIT_OBJECT_0:
00073 break;
00074
00075
00076 case WAIT_TIMEOUT:
00077 return FALSE;
00078
00079
00080 case WAIT_ABANDONED:
00081 break;
00082
00083
00084 case WAIT_FAILED:
00085 return FALSE;
00086 }
00087
00088 return TRUE;
00089
00090 }
00091
00092 void Mutex::Wait()
00093 {
00094 while(WaitWithTimeout(INFINITE) == FALSE) {}
00095 }
00096
00097 bool Mutex::TryWait()
00098 {
00099 return WaitWithTmeout(0);
00100 }
00101
00102 void Mutex::Release()
00103 {
00104 ReleaseMutex(m_mutex);
00105 }
00106
00107 #endif // _WIN32
00108
00109
00110
00111 ScopedMutex::ScopedMutex(Mutex & mutex) : m_mutex(mutex)
00112 {
00113 m_mutex.Wait();
00114 }
00115 ScopedMutex::~ScopedMutex()
00116 {
00117 m_mutex.Release();
00118 }
00119
00120
00121 Semaphore::Semaphore(int count) : m_count(count) {}
00122 Semaphore::Semaphore() : m_count(0) {}
00123
00125
00126 void Semaphore::Wait()
00127 {
00128 m_mutex.Wait();
00129 while(m_count == 0)
00130 {
00131 m_mutex.Release();
00132 #ifdef _WIN32
00133 Sleep(0);
00134 #endif
00135 #ifdef LINUX
00136 sched_yield();
00137 #endif
00138 m_mutex.Wait();
00139 }
00140 m_count--;
00141 m_mutex.Release();
00142 }
00143
00144 bool Semaphore::TryWait()
00145 {
00146 m_mutex.Wait();
00147 if(m_count == 0)
00148 {
00149 return false;
00150 }
00151 m_count--;
00152 m_mutex.Release();
00153 return true;
00154 }
00155
00156 bool Semaphore::Wait(int millisecondTimeout)
00157 {
00158 #ifdef _WIN32
00159 int timeout = GetTickCount() + millisecondTimeout;
00160 #endif
00161 #ifdef LINUX
00162 timeb timeout;
00163 ftime(&timeout);
00164 int tempMilli = (int)timeout.millitm + millisecondTimeout;
00165 timeout.time = timeout.time + tempMilli/1000;
00166 timeout.millitm = tempMilli /1000;
00167 #endif
00168 m_mutex.Wait();
00169 while(m_count == 0)
00170 {
00171 m_mutex.Release();
00172 #ifdef _WIN32
00173 Sleep(0);
00174 if(GetTickCount() > timeout) return false;
00175 #endif
00176 #ifdef LINUX
00177 sched_yield();
00178 timeb curtime;
00179 ftime(&curtime);
00180 if((timeout.time <= curtime.time) && (timeout.millitm <= curtime.millitm))
00181 {
00182 return false;
00183 }
00184 #endif
00185 m_mutex.Wait();
00186 }
00187 m_count--;
00188 m_mutex.Release();
00189 return true;
00190 }
00191
00192 void Semaphore::Signal()
00193 {
00194 m_mutex.Wait();
00195 m_count++;
00196 m_mutex.Release();
00197 }
00198
00199 Thread::Thread() {}
00200 Thread::~Thread()
00201 {
00202 m_mutex.Release();
00203 }
00204 void Thread::Start()
00205 {
00206 m_mutex.Wait();
00207 #ifdef _WIN32
00208 m_threadHandle = beginthread(StartThread, 0, this);
00209 #endif
00210 #ifdef LINUX
00211 pthread_create(&m_threadHandle, NULL, StartThread, this);
00212 #endif
00213 }
00214 void Thread::Go()
00215 {
00216 Function();
00217 m_mutex.Release();
00218 }
00219
00220 void Thread::Yield()
00221 {
00222 #ifdef _WIN32
00223 Sleep(0);
00224 #endif
00225 #ifdef LINUX
00226 sched_yield();
00227 #endif
00228 }
00229 void Thread::Join()
00230 {
00231 if(pthread_join(m_threadHandle, NULL))
00232 assert(0);
00233 }
00234 }