Skip to content

Instantly share code, notes, and snippets.

@kevgs
Last active May 12, 2020 13:44
Show Gist options
  • Save kevgs/4458ecb33f53784ea75336aa883aad6f to your computer and use it in GitHub Desktop.
Save kevgs/4458ecb33f53784ea75336aa883aad6f to your computer and use it in GitHub Desktop.
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