template <typename BatonType>
void TimedRWMutex<BatonType>::read_lock() {
template <typename BatonType>
void TimedRWMutex<BatonType>::read_lock() {
- pthread_spin_lock(&lock_);
if (state_ == State::WRITE_LOCKED) {
MutexWaiter waiter;
read_waiters_.push_back(waiter);
if (state_ == State::WRITE_LOCKED) {
MutexWaiter waiter;
read_waiters_.push_back(waiter);
- pthread_spin_unlock(&lock_);
waiter.baton.wait();
assert(state_ == State::READ_LOCKED);
return;
waiter.baton.wait();
assert(state_ == State::READ_LOCKED);
return;
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
- pthread_spin_unlock(&lock_);
}
template <typename BatonType>
template <typename Rep, typename Period>
bool TimedRWMutex<BatonType>::timed_read_lock(
const std::chrono::duration<Rep, Period>& duration) {
}
template <typename BatonType>
template <typename Rep, typename Period>
bool TimedRWMutex<BatonType>::timed_read_lock(
const std::chrono::duration<Rep, Period>& duration) {
- pthread_spin_lock(&lock_);
if (state_ == State::WRITE_LOCKED) {
MutexWaiter waiter;
read_waiters_.push_back(waiter);
if (state_ == State::WRITE_LOCKED) {
MutexWaiter waiter;
read_waiters_.push_back(waiter);
- pthread_spin_unlock(&lock_);
if (!waiter.baton.timed_wait(duration)) {
// We timed out. Two cases:
if (!waiter.baton.timed_wait(duration)) {
// We timed out. Two cases:
// 2. We're not in the waiter list anymore. This could happen if the baton
// times out but the mutex is unlocked before we reach this code. In
// this case we'll pretend we got the lock on time.
// 2. We're not in the waiter list anymore. This could happen if the baton
// times out but the mutex is unlocked before we reach this code. In
// this case we'll pretend we got the lock on time.
- pthread_spin_lock(&lock_);
if (waiter.hook.is_linked()) {
read_waiters_.erase(read_waiters_.iterator_to(waiter));
if (waiter.hook.is_linked()) {
read_waiters_.erase(read_waiters_.iterator_to(waiter));
- pthread_spin_unlock(&lock_);
- pthread_spin_unlock(&lock_);
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
- pthread_spin_unlock(&lock_);
return true;
}
template <typename BatonType>
bool TimedRWMutex<BatonType>::try_read_lock() {
return true;
}
template <typename BatonType>
bool TimedRWMutex<BatonType>::try_read_lock() {
- pthread_spin_lock(&lock_);
if (state_ != State::WRITE_LOCKED) {
assert(
(state_ == State::UNLOCKED && readers_ == 0) ||
if (state_ != State::WRITE_LOCKED) {
assert(
(state_ == State::UNLOCKED && readers_ == 0) ||
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
assert(read_waiters_.empty());
state_ = State::READ_LOCKED;
readers_ += 1;
- pthread_spin_unlock(&lock_);
- pthread_spin_unlock(&lock_);
return false;
}
template <typename BatonType>
void TimedRWMutex<BatonType>::write_lock() {
return false;
}
template <typename BatonType>
void TimedRWMutex<BatonType>::write_lock() {
- pthread_spin_lock(&lock_);
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
- pthread_spin_unlock(&lock_);
return;
}
MutexWaiter waiter;
write_waiters_.push_back(waiter);
return;
}
MutexWaiter waiter;
write_waiters_.push_back(waiter);
- pthread_spin_unlock(&lock_);
template <typename Rep, typename Period>
bool TimedRWMutex<BatonType>::timed_write_lock(
const std::chrono::duration<Rep, Period>& duration) {
template <typename Rep, typename Period>
bool TimedRWMutex<BatonType>::timed_write_lock(
const std::chrono::duration<Rep, Period>& duration) {
- pthread_spin_lock(&lock_);
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
- pthread_spin_unlock(&lock_);
return true;
}
MutexWaiter waiter;
write_waiters_.push_back(waiter);
return true;
}
MutexWaiter waiter;
write_waiters_.push_back(waiter);
- pthread_spin_unlock(&lock_);
if (!waiter.baton.timed_wait(duration)) {
// We timed out. Two cases:
if (!waiter.baton.timed_wait(duration)) {
// We timed out. Two cases:
// 2. We're not in the waiter list anymore. This could happen if the baton
// times out but the mutex is unlocked before we reach this code. In
// this case we'll pretend we got the lock on time.
// 2. We're not in the waiter list anymore. This could happen if the baton
// times out but the mutex is unlocked before we reach this code. In
// this case we'll pretend we got the lock on time.
- pthread_spin_lock(&lock_);
if (waiter.hook.is_linked()) {
write_waiters_.erase(write_waiters_.iterator_to(waiter));
if (waiter.hook.is_linked()) {
write_waiters_.erase(write_waiters_.iterator_to(waiter));
- pthread_spin_unlock(&lock_);
- pthread_spin_unlock(&lock_);
}
assert(state_ == State::WRITE_LOCKED);
return true;
}
assert(state_ == State::WRITE_LOCKED);
return true;
template <typename BatonType>
bool TimedRWMutex<BatonType>::try_write_lock() {
template <typename BatonType>
bool TimedRWMutex<BatonType>::try_write_lock() {
- pthread_spin_lock(&lock_);
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
if (state_ == State::UNLOCKED) {
verify_unlocked_properties();
state_ = State::WRITE_LOCKED;
- pthread_spin_unlock(&lock_);
- pthread_spin_unlock(&lock_);
return false;
}
template <typename BatonType>
void TimedRWMutex<BatonType>::unlock() {
return false;
}
template <typename BatonType>
void TimedRWMutex<BatonType>::unlock() {
- pthread_spin_lock(&lock_);
assert(state_ != State::UNLOCKED);
assert(
(state_ == State::READ_LOCKED && readers_ > 0) ||
assert(state_ != State::UNLOCKED);
assert(
(state_ == State::READ_LOCKED && readers_ > 0) ||
} else {
assert(state_ == State::READ_LOCKED);
}
} else {
assert(state_ == State::READ_LOCKED);
}
- pthread_spin_unlock(&lock_);
}
template <typename BatonType>
void TimedRWMutex<BatonType>::downgrade() {
}
template <typename BatonType>
void TimedRWMutex<BatonType>::downgrade() {
- pthread_spin_lock(&lock_);
assert(state_ == State::WRITE_LOCKED && readers_ == 0);
state_ = State::READ_LOCKED;
readers_ += 1;
assert(state_ == State::WRITE_LOCKED && readers_ == 0);
state_ = State::READ_LOCKED;
readers_ += 1;
to_wake.baton.post();
}
}
to_wake.baton.post();
}
}
- pthread_spin_unlock(&lock_);
#include <folly/IntrusiveList.h>
#include <folly/SpinLock.h>
#include <folly/fibers/GenericBaton.h>
#include <folly/IntrusiveList.h>
#include <folly/SpinLock.h>
#include <folly/fibers/GenericBaton.h>
template <typename BatonType>
class TimedRWMutex {
public:
template <typename BatonType>
class TimedRWMutex {
public:
- TimedRWMutex() {
- pthread_spin_init(&lock_, PTHREAD_PROCESS_PRIVATE);
- }
-
- ~TimedRWMutex() {
- pthread_spin_destroy(&lock_);
- }
+ TimedRWMutex() = default;
+ ~TimedRWMutex() = default;
TimedRWMutex(const TimedRWMutex& rhs) = delete;
TimedRWMutex& operator=(const TimedRWMutex& rhs) = delete;
TimedRWMutex(const TimedRWMutex& rhs) = delete;
TimedRWMutex& operator=(const TimedRWMutex& rhs) = delete;
boost::intrusive::constant_time_size<true>>
MutexWaiterList;
boost::intrusive::constant_time_size<true>>
MutexWaiterList;
- pthread_spinlock_t lock_; //< lock protecting the internal state
+ folly::SpinLock lock_; //< lock protecting the internal state
// (state_, read_waiters_, etc.)
State state_ = State::UNLOCKED;
// (state_, read_waiters_, etc.)
State state_ = State::UNLOCKED;