Go to the documentation of this file.00001
00020 #ifndef COIL_CONDITION_H
00021 #define COIL_CONDITION_H
00022
00023 #include <windows.h>
00024 #include <algorithm>
00025 #include <coil/Mutex.h>
00026 #include <iostream>
00027
00028 namespace coil
00029 {
00030 typedef struct
00031 {
00032
00033 int waiters_count_;
00034
00035
00036 coil::Mutex waiters_count_lock_;
00037
00038
00039
00040 HANDLE sema_;
00041
00042
00043
00044
00045 HANDLE waiters_done_;
00046
00047
00048
00049 size_t was_broadcast_;
00050
00051 } pthread_cond_t;
00052
00053
00054 static int pthread_cond_init (pthread_cond_t *cv)
00055 {
00056 cv->waiters_count_ = 0;
00057 cv->was_broadcast_ = 0;
00058 cv->sema_ = ::CreateSemaphore (NULL,
00059 0,
00060 0x7fffffff,
00061 NULL);
00062 cv->waiters_done_ = ::CreateEvent (NULL,
00063 FALSE,
00064 FALSE,
00065 NULL);
00066 return 0;
00067 }
00068
00082 template <class M>
00083 class Condition
00084 {
00085 public:
00086
00102 Condition(M& mutex)
00103 : m_mutex(mutex)
00104 {
00105 pthread_cond_init(&m_cond);
00106 }
00107
00123 ~Condition()
00124 {
00125 }
00126
00142 inline void signal()
00143 {
00144 pthread_cond_signal(&m_cond);
00145 }
00146
00162 inline void broadcast()
00163 {
00164 pthread_cond_broadcast(&m_cond);
00165 }
00166
00186 bool wait()
00187 {
00188 return 0 == pthread_cond_wait(&m_cond, &m_mutex, INFINITE);
00189 }
00190
00216 bool wait(long second, long nano_second = 0)
00217 {
00218 DWORD milli_second = second * 1000 + nano_second / 1000000;
00219 return 0 == pthread_cond_wait(&m_cond, &m_mutex, milli_second);
00220 }
00221
00222 private:
00223
00243 int pthread_cond_wait (coil::pthread_cond_t *cv, coil::Mutex *external_mutex, DWORD aMilliSecond)
00244 {
00245 DWORD result;
00246
00247
00248 cv->waiters_count_lock_.lock();
00249 cv->waiters_count_++;
00250 cv->waiters_count_lock_.unlock();
00251
00252
00253
00254
00255
00256 result = SignalObjectAndWait (external_mutex->mutex_, cv->sema_, aMilliSecond, FALSE);
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 cv->waiters_count_lock_.lock();
00279
00280
00281 cv->waiters_count_--;
00282
00283
00284 int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
00285
00286 cv->waiters_count_lock_.unlock();
00287
00288
00289
00290 if (last_waiter) {
00291
00292
00293
00294 DWORD result = SignalObjectAndWait (cv->waiters_done_, external_mutex->mutex_, INFINITE, FALSE);
00295
00296 } else {
00297
00298
00299 ::WaitForSingleObject (external_mutex->mutex_, 0);
00300 }
00301 return result;
00302 }
00303
00323 int pthread_cond_signal (pthread_cond_t *cv)
00324 {
00325 cv->waiters_count_lock_.lock();
00326 int have_waiters = cv->waiters_count_ > 0;
00327 cv->waiters_count_lock_.unlock();
00328
00329
00330 if (have_waiters)
00331
00332 ReleaseSemaphore (cv->sema_, 1, 0);
00333
00334 return 0;
00335 }
00336
00356 int pthread_cond_broadcast (pthread_cond_t *cv)
00357 {
00358
00359
00360 cv->waiters_count_lock_.lock();
00361 int have_waiters = 0;
00362
00363 if (cv->waiters_count_ > 0) {
00364
00365
00366
00367 cv->was_broadcast_ = 1;
00368 have_waiters = 1;
00369 }
00370
00371 if (have_waiters) {
00372
00373
00374 ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
00375
00376
00377 cv->waiters_count_lock_.unlock();
00378
00379
00380
00381 WaitForSingleObject (cv->waiters_done_, INFINITE);
00382
00383
00384 cv->was_broadcast_ = 0;
00385 }
00386 else
00387 cv->waiters_count_lock_.unlock();
00388 return 0;
00389 }
00390
00391 Condition(const Mutex&);
00392 Condition& operator=(const Mutex &);
00393 coil::pthread_cond_t m_cond;
00394 M& m_mutex;
00395 };
00396
00397 };
00398 #endif // COIL_CONDITION_H