dthread-win.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "common/h/dthread.h"
00031 #include <assert.h>
00032
00033 DThread::DThread()
00034 {
00035 }
00036
00037 DThread::~DThread()
00038 {
00039 }
00040
00041 long DThread::self()
00042 {
00043 return ::GetCurrentThreadId();
00044 }
00045 bool DThread::spawn(DThread::initial_func_t func, void *param)
00046 {
00047 thrd = ::CreateThread(NULL, 0, func, param, 0, &tid);
00048 live = (thrd != INVALID_HANDLE_VALUE);
00049 return live;
00050 }
00051 bool DThread::join()
00052 {
00053 assert(live && self() != id());
00054 ::WaitForSingleObject(thrd, INFINITE);
00055 return true;
00056 }
00057
00058 long DThread::id()
00059 {
00060 return tid;
00061 }
00062
00063
00064 Mutex::Mutex(bool recursive)
00065 {
00066 mutex = ::CreateMutex(NULL, false, NULL);
00067 }
00068
00069 Mutex::~Mutex()
00070 {
00071 ::CloseHandle(mutex);
00072 }
00073
00074 bool Mutex::lock()
00075 {
00076
00077 bool ok = (::WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0);
00078
00079 return ok;
00080 }
00081
00082 bool Mutex::unlock()
00083 {
00084
00085 bool ok = (::ReleaseMutex(mutex) != 0);
00086 if(!ok) {
00087 fprintf(stderr, "Failed to release mutex: %d\n", ::GetLastError());
00088 }
00089 return ok;
00090 }
00091
00092 CondVar::CondVar(Mutex *m) :
00093 numWaiting(0),
00094 was_broadcast(false),
00095 mutex(m),
00096 created_mutex(false)
00097 {
00098 if(mutex == NULL)
00099 {
00100 mutex = new Mutex();
00101 created_mutex = true;
00102 }
00103 wait_sema = ::CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
00104 ::InitializeCriticalSection(&numWaitingLock);
00105 wait_done = ::CreateEvent(NULL, false, false, NULL);
00106 }
00107 CondVar::~CondVar()
00108 {
00109 if(created_mutex)
00110 {
00111 delete mutex;
00112 }
00113 ::CloseHandle(wait_sema);
00114 ::CloseHandle(wait_done);
00115 ::DeleteCriticalSection(&numWaitingLock);
00116 }
00117
00118 bool CondVar::unlock()
00119 {
00120 bool ret = mutex->unlock();
00121 return ret;
00122 }
00123 bool CondVar::lock()
00124 {
00125 bool ret = mutex->lock();
00126 return ret;
00127 }
00128 bool CondVar::signal()
00129 {
00130 ::EnterCriticalSection(&numWaitingLock);
00131 bool waitingThreads = (numWaiting > 0);
00132 ::LeaveCriticalSection(&numWaitingLock);
00133 if(waitingThreads)
00134 {
00135 long prev_count;
00136 ::ReleaseSemaphore(wait_sema, 1, &prev_count);
00137
00138 }
00139 return true;
00140 }
00141 bool CondVar::broadcast()
00142 {
00143 ::EnterCriticalSection(&numWaitingLock);
00144 bool waitingThreads = (numWaiting > 0);
00145 was_broadcast = true;
00146 if(waitingThreads)
00147 {
00148 long prev_count;
00149 ::ReleaseSemaphore(wait_sema, numWaiting, &prev_count);
00150
00151 ::LeaveCriticalSection(&numWaitingLock);
00152 ::WaitForSingleObject(wait_done, INFINITE);
00153 was_broadcast = false;
00154 }
00155 else
00156 {
00157 ::LeaveCriticalSection(&numWaitingLock);
00158 }
00159 return true;
00160 }
00161 bool CondVar::wait()
00162 {
00163 ::EnterCriticalSection(&numWaitingLock);
00164 numWaiting++;
00165 ::LeaveCriticalSection(&numWaitingLock);
00166
00167 unsigned long result = ::SignalObjectAndWait(mutex->mutex, wait_sema, INFINITE, FALSE);
00168 assert(result != WAIT_TIMEOUT);
00169 ::EnterCriticalSection(&numWaitingLock);
00170 numWaiting--;
00171 bool last_waiter = (was_broadcast && (numWaiting == 0));
00172 ::LeaveCriticalSection(&numWaitingLock);
00173 if(last_waiter)
00174 {
00175
00176 result = ::SignalObjectAndWait(wait_done, mutex->mutex, INFINITE, FALSE);
00177 assert(result != WAIT_TIMEOUT);
00178 }
00179 else
00180 {
00181 ::WaitForSingleObject(mutex->mutex, INFINITE);
00182 }
00183 return true;
00184 }