00001
00002
00003 #include <windows.h>
00004
00005 namespace dynamic
00006 {
00007 namespace api
00008 {
00010
00011 class mutex : cg::not_copyable, cg::not_assignable
00012 {
00013 public:
00014 mutex()
00015 {
00016 InitializeCriticalSection(&m_cs);
00017 }
00018
00019 ~mutex()
00020 {
00021 DeleteCriticalSection(&m_cs);
00022 }
00023
00024 void lock()
00025 {
00026 EnterCriticalSection(&m_cs);
00027 }
00028
00029 void unlock()
00030 {
00031 LeaveCriticalSection(&m_cs);
00032 }
00033
00034 private:
00035 CRITICAL_SECTION m_cs;
00036 mutex(const mutex&);
00037 };
00038
00039
00041
00042 class thread : cg::not_copyable, cg::not_assignable
00043 {
00044 HANDLE h_thread;
00045 typedef void thread_func(void*);
00046 thread_func *m_fn;
00047 void * m_data;
00048
00049 static DWORD WINAPI thread_proc(LPVOID param)
00050 {
00051 thread * self = static_cast<thread*>(param);
00052 self->m_fn(self->m_data);
00053 return 0;
00054 };
00055
00056 public:
00057 thread() : h_thread(INVALID_HANDLE_VALUE)
00058 {
00059 }
00060
00061 void run(thread_func start, LPVOID data)
00062 {
00063 m_fn = start;
00064 m_data = data;
00065 h_thread = ::CreateThread(0, 0, &thread_proc, this, 0, 0);
00066 }
00067
00068 ~thread()
00069 {
00070 if(h_thread != INVALID_HANDLE_VALUE) CloseHandle(h_thread);
00071 }
00072
00073 void join()
00074 {
00075 ::WaitForSingleObject(h_thread, INFINITE);
00076 }
00077 };
00078
00079
00081 class event : cg::not_copyable, cg::not_assignable
00082 {
00083 HANDLE m_handle;
00084
00085 public:
00086 event()
00087 {
00088 m_handle = ::CreateEvent(0, 0, 0, 0);
00089 }
00090
00091 ~event()
00092 {
00093 if(m_handle != INVALID_HANDLE_VALUE) ::CloseHandle(m_handle);
00094 }
00095
00096 void wait()
00097 {
00098 ::WaitForSingleObject(m_handle, INFINITE);
00099 }
00100
00101 void signal()
00102 {
00103 ::SetEvent(m_handle);
00104 }
00105 };
00106
00107
00109 inline void sleep(int s)
00110 {
00111 ::Sleep(s * 1000);
00112 }
00113
00114
00115 #if defined(__CYGWIN__)
00116 typedef long int interlocked_var;
00117 #else
00118 typedef LONG volatile interlocked_var;
00119 #endif
00120
00122
00123 class atomic_counter
00124 {
00125 public:
00126 atomic_counter() : m_counter(0)
00127 {
00128 }
00129
00130 LONG operator++()
00131 {
00132 return InterlockedIncrement(&m_counter);
00133 }
00134
00135 LONG operator++(int)
00136 {
00137 return InterlockedIncrement(&m_counter)-1;
00138 }
00139
00140 LONG operator--()
00141 {
00142 return InterlockedDecrement(&m_counter);
00143 }
00144
00145 LONG operator--(int)
00146 {
00147 return InterlockedDecrement(&m_counter)+1;
00148 }
00149
00150 private:
00151 interlocked_var m_counter;
00152 };
00153
00154
00156
00160 class stack : cg::not_copyable, cg::not_assignable
00161 {
00162 int m_size;
00163 bool m_shutdown;
00164 CRITICAL_SECTION m_cs;
00165 HANDLE m_item_available, m_empty;
00166
00167 public:
00169 stack() :
00170 m_size(0),
00171 m_shutdown(false),
00172 m_item_available(::CreateEvent(0, 1, 0, 0)),
00173 m_empty(::CreateEvent(0, 1, 1, 0))
00174 {
00175 ::InitializeCriticalSection(&m_cs);
00176 }
00177
00178 ~stack()
00179 {
00180 ::DeleteCriticalSection(&m_cs);
00181 ::CloseHandle(m_empty);
00182 ::CloseHandle(m_item_available);
00183 }
00184
00186 void shutdown()
00187 {
00188 EnterCriticalSection(&m_cs);
00189 m_shutdown = true;
00190 ::SetEvent(m_item_available);
00191 LeaveCriticalSection(&m_cs);
00192 }
00193
00195 bool check_shutdown()
00196 {
00197 EnterCriticalSection(&m_cs);
00198 bool ret = m_shutdown;
00199 LeaveCriticalSection(&m_cs);
00200 return ret;
00201 }
00202
00204 void push()
00205 {
00206 EnterCriticalSection(&m_cs);
00207 ++m_size;
00208 ::SetEvent(m_item_available);
00209 ::ResetEvent(m_empty);
00210 LeaveCriticalSection(&m_cs);
00211 }
00212
00214
00215 bool wait_pop()
00216 {
00217 EnterCriticalSection(&m_cs);
00218 while(m_size==0 && !m_shutdown)
00219 {
00220 LeaveCriticalSection(&m_cs);
00221 WaitForSingleObject(m_item_available, INFINITE);
00222 EnterCriticalSection(&m_cs);
00223 }
00224 if(m_shutdown)
00225 {
00226 LeaveCriticalSection(&m_cs);
00227 return false;
00228 }
00229 --m_size;
00230 if(m_size==0)
00231 {
00232 ::ResetEvent(m_item_available);
00233 ::SetEvent(m_empty);
00234 }
00235 LeaveCriticalSection(&m_cs);
00236 return true;
00237 }
00238
00240 void wait_empty()
00241 {
00242 WaitForSingleObject(m_empty, INFINITE);
00243 }
00244 };
00245 }
00246 }