Skip to content

Instantly share code, notes, and snippets.

@melpon
Created June 19, 2012 14:37
Show Gist options
  • Save melpon/2954555 to your computer and use it in GitHub Desktop.
Save melpon/2954555 to your computer and use it in GitHub Desktop.
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