Created
June 19, 2012 14:37
-
-
Save melpon/2954555 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum cv_status { cvs_no_timeout, cvs_timeout }; | |
class condition_variable { | |
typedef pthread_cond_t native_type; | |
native_type cond_; | |
public: | |
typedef native_type* native_handle_type; | |
condition_variable() { | |
int e = pthread_cond_init(&cond_, 0); | |
if (e != 0) | |
throw e; | |
} | |
~condition_variable() { | |
int e = pthread_cond_destroy(&cond_); | |
assert(e == 0); | |
} | |
private: | |
condition_variable(const condition_variable&); | |
condition_variable& operator=(const condition_variable&); | |
public: | |
void notify_one() { | |
int e = pthread_cond_signal(&cond_); | |
if (e) | |
throw e; | |
} | |
void notify_all() { | |
int e = pthread_cond_broadcast(&cond_); | |
if (e) | |
throw e; | |
} | |
void wait(unique_lock<mutex>& lock) { | |
int e = pthread_cond_wait(&cond_, lock.mutex()->native_handle()); | |
if (e) | |
throw e; | |
} | |
template<typename Predicate> | |
void wait(unique_lock<mutex>& lock, Predicate p) { | |
while (!p()) | |
wait(lock); | |
} | |
cv_status wait_until(unique_lock<mutex>& lock, const timespec& ts) { | |
pthread_cond_timedwait(&cond_, lock.mutex()->native_handle(), &ts); | |
timespec now = time_detail::get_now(); | |
return now < ts ? cvs_no_timeout : cvs_timeout; | |
} | |
template<typename Predicate> | |
cv_status wait_until(unique_lock<mutex>& lock, const timespec& ts, Predicate p) { | |
while (!p()) | |
if (wait_until(lock, ts) == cvs_timeout) | |
return p(); | |
return true; | |
} | |
cv_status wait_for(unique_lock<mutex>& lock, double seconds) { | |
return wait_until(lock, time_detail::to_abs(seconds)); | |
} | |
template<typename Predicate> | |
bool wait_for(unique_lock<mutex>& lock, double seconds, Predicate p) { | |
return wait_until(lock, time_detail::to_abs(seconds), p); | |
} | |
native_handle_type native_handle() { return &cond_; } | |
}; | |
class condition_variable_any { | |
condition_variable cond_; | |
mutex mutex_; | |
public: | |
condition_variable_any() { } | |
~condition_variable_any() { } | |
private: | |
condition_variable_any(const condition_variable_any&); | |
condition_variable_any& operator=(const condition_variable_any&); | |
public: | |
void notify_one() { | |
lock_guard<mutex> lock(mutex_); | |
cond_.notify_one(); | |
} | |
void notify_all() { | |
lock_guard<mutex> lock(mutex_); | |
cond_.notify_all(); | |
} | |
template<typename Lock> | |
void wait(Lock& lock) { | |
struct scoped_unlock { | |
explicit scoped_unlock(Lock& lk) : lock_(lk) { lk.unlock(); } | |
~scoped_unlock() { | |
lock_.lock(); | |
} | |
Lock& lock_; | |
}; | |
unique_lock<mutex> my_lock(mutex_); | |
scoped_unlock unlock(lock); | |
unique_lock<mutex> my_lock2; | |
my_lock2.swap(my_lock); | |
cond_.wait(my_lock2); | |
} | |
template<typename Lock, typename Predicate> | |
void wait(Lock& lock, Predicate p) { | |
while (!p()) | |
wait(lock); | |
} | |
template<typename Lock> | |
cv_status wait_until(Lock& lock, const timespec& ts) { | |
unique_lock<mutex> my_lock(mutex_); | |
lock.unlock(); | |
cv_status status = cond_.wait_until(my_lock, ts); | |
lock.lock(); | |
return status; | |
} | |
template<typename Lock, typename Predicate> | |
bool wait_until(Lock& lock, const timespec& ts, Predicate p) { | |
while (!p()) | |
if (wait_until(lock, ts) == cvs_timeout) | |
return p(); | |
return true; | |
} | |
template<typename Lock> | |
cv_status wait_for(Lock& lock, double seconds) { | |
return wait_until(lock, time_detail::to_abs(seconds)); | |
} | |
template<typename Lock, typename Predicate> | |
bool wait_for(Lock& lock, double seconds, Predicate p) { | |
return wait_until(lock, time_detail::to_abs(seconds), p); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment