Last active
May 12, 2020 13:44
-
-
Save kevgs/4458ecb33f53784ea75336aa883aad6f to your computer and use it in GitHub Desktop.
This file contains hidden or 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
class PMutex | |
{ | |
pthread_mutex_t mutex_; | |
public: | |
using native_handle_type= pthread_mutex_t &; | |
PMutex() | |
{ | |
pthread_mutexattr_t attr; | |
auto ret= pthread_mutexattr_init(&attr); | |
assert(ret == 0); | |
ret= pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); | |
assert(ret == 0); | |
ret= pthread_mutex_init(&mutex_, &attr); | |
assert(ret == 0); | |
ret= pthread_mutexattr_destroy(&attr); | |
assert(ret == 0); | |
} | |
PMutex(const PMutex &)= delete; | |
PMutex(PMutex &&)= delete; | |
PMutex &operator=(const PMutex &)= delete; | |
PMutex &operator=(PMutex &&)= delete; | |
~PMutex() | |
{ | |
auto ret= pthread_mutex_destroy(&mutex_); | |
assert(ret == 0); | |
} | |
native_handle_type native_handle() { return mutex_; } | |
void lock() | |
{ | |
auto ret= pthread_mutex_lock(&mutex_); | |
assert(ret == 0); | |
} | |
bool try_lock() | |
{ | |
auto ret= pthread_mutex_trylock(&mutex_); | |
switch (ret) | |
{ | |
case 0: | |
return true; | |
case EBUSY: | |
return false; | |
default: | |
assert(0); | |
} | |
__builtin_unreachable(); | |
} | |
void unlock() | |
{ | |
auto ret= pthread_mutex_unlock(&mutex_); | |
assert(ret == 0); | |
} | |
}; | |
class PCondvar | |
{ | |
pthread_cond_t cond_; | |
public: | |
PCondvar() | |
{ | |
pthread_condattr_t attr; | |
auto ret= pthread_condattr_init(&attr); | |
assert(ret == 0); | |
ret= pthread_cond_init(&cond_, &attr); | |
assert(ret == 0); | |
ret= pthread_condattr_destroy(&attr); | |
assert(ret == 0); | |
} | |
PCondvar(const PCondvar &)= delete; | |
PCondvar(PCondvar &&)= delete; | |
PCondvar &operator=(const PCondvar &)= delete; | |
PCondvar &operator=(PCondvar &&)= delete; | |
~PCondvar() | |
{ | |
auto ret= pthread_cond_destroy(&cond_); | |
assert(ret == 0); | |
} | |
void notify_one() | |
{ | |
auto ret= pthread_cond_signal(&cond_); | |
assert(ret == 0); | |
} | |
void notify_all() | |
{ | |
auto ret= pthread_cond_broadcast(&cond_); | |
assert(ret == 0); | |
} | |
void wait(std::unique_lock<PMutex> &lock) | |
{ | |
auto ret= pthread_cond_wait(&cond_, &lock.mutex()->native_handle()); | |
switch (ret) | |
{ | |
case 0: | |
return; | |
default: | |
assert(0); | |
} | |
} | |
template <class Rep, class Period> | |
std::cv_status wait_for(std::unique_lock<PMutex> &lock, | |
const std::chrono::duration<Rep, Period> &rel_time) | |
{ | |
auto seconds= | |
std::chrono::duration_cast<std::chrono::seconds>(rel_time).count(); | |
auto nanoseconds= | |
std::chrono::duration_cast<std::chrono::nanoseconds>(rel_time) | |
.count() % | |
1000000000; | |
timespec now; | |
auto ret= clock_gettime(CLOCK_REALTIME, &now); | |
assert(ret == 0); | |
timespec ts{now.tv_sec + seconds, now.tv_nsec + nanoseconds}; | |
switch ( | |
pthread_cond_timedwait(&cond_, &lock.mutex()->native_handle(), &ts)) | |
{ | |
case 0: | |
return std::cv_status::no_timeout; | |
case ETIMEDOUT: | |
return std::cv_status::timeout; | |
default: | |
assert(0); | |
} | |
__builtin_unreachable(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment