proxygen
folly::fibers::TimedMutex Class Reference

#include <TimedMutex.h>

Classes

struct  MutexWaiter
 

Public Member Functions

 TimedMutex () noexcept
 
 ~TimedMutex ()
 
 TimedMutex (const TimedMutex &rhs)=delete
 
TimedMutexoperator= (const TimedMutex &rhs)=delete
 
 TimedMutex (TimedMutex &&rhs)=delete
 
TimedMutexoperator= (TimedMutex &&rhs)=delete
 
void lock ()
 
template<typename Rep , typename Period >
bool timed_lock (const std::chrono::duration< Rep, Period > &duration)
 
bool try_lock ()
 
void unlock ()
 

Private Types

enum  LockResult { LockResult::SUCCESS, LockResult::TIMEOUT, LockResult::STOLEN }
 
using MutexWaiterList = folly::IntrusiveList< MutexWaiter,&MutexWaiter::hook >
 

Private Member Functions

template<typename WaitFunc >
LockResult lockHelper (WaitFunc &&waitFunc)
 

Private Attributes

folly::SpinLock lock_
 
bool locked_ = false
 
MutexWaiterList threadWaiters_
 
MutexWaiterList fiberWaiters_
 
MutexWaiternotifiedFiber_ {nullptr}
 

Detailed Description

Like mutex but allows timed_lock in addition to lock and try_lock.

Definition at line 30 of file TimedMutex.h.

Member Typedef Documentation

Member Enumeration Documentation

Enumerator
SUCCESS 
TIMEOUT 
STOLEN 

Definition at line 61 of file TimedMutex.h.

Constructor & Destructor Documentation

folly::fibers::TimedMutex::TimedMutex ( )
inlinenoexcept

Definition at line 32 of file TimedMutex.h.

Referenced by ~TimedMutex().

32 {}
folly::fibers::TimedMutex::~TimedMutex ( )
inline

Definition at line 34 of file TimedMutex.h.

References fiberWaiters_, lock(), notifiedFiber_, operator=(), folly::detail::rhs, threadWaiters_, timed_lock(), TimedMutex(), try_lock(), and unlock().

34  {
35  DCHECK(threadWaiters_.empty());
36  DCHECK(fiberWaiters_.empty());
37  DCHECK(notifiedFiber_ == nullptr);
38  }
MutexWaiterList fiberWaiters_
Definition: TimedMutex.h:78
MutexWaiterList threadWaiters_
Definition: TimedMutex.h:77
MutexWaiter * notifiedFiber_
Definition: TimedMutex.h:79
folly::fibers::TimedMutex::TimedMutex ( const TimedMutex rhs)
delete
folly::fibers::TimedMutex::TimedMutex ( TimedMutex &&  rhs)
delete

Member Function Documentation

void folly::fibers::TimedMutex::lock ( )
inline

Definition at line 81 of file TimedMutex-inl.h.

References folly::fibers::TimedMutex::MutexWaiter::baton, lockHelper(), SUCCESS, TIMEOUT, and folly::fibers::Baton::wait().

Referenced by TEST(), timed_lock(), and ~TimedMutex().

81  {
82  auto result = lockHelper([](MutexWaiter& waiter) {
83  waiter.baton.wait();
84  return true;
85  });
86 
87  DCHECK(result != LockResult::TIMEOUT);
88  if (result == LockResult::SUCCESS) {
89  return;
90  }
91  lock();
92 }
LockResult lockHelper(WaitFunc &&waitFunc)
template<typename WaitFunc >
TimedMutex::LockResult folly::fibers::TimedMutex::lockHelper ( WaitFunc &&  waitFunc)
private

Definition at line 28 of file TimedMutex-inl.h.

References fiberWaiters_, lock_, locked_, notifiedFiber_, folly::fibers::onFiber(), STOLEN, SUCCESS, threadWaiters_, TIMEOUT, and folly::ulock().

Referenced by lock(), and timed_lock().

28  {
29  std::unique_lock<folly::SpinLock> ulock(lock_);
30  if (!locked_) {
31  locked_ = true;
32  return LockResult::SUCCESS;
33  }
34 
35  const auto isOnFiber = onFiber();
36 
37  if (!isOnFiber && notifiedFiber_ != nullptr) {
38  // lock() was called on a thread and while some other fiber was already
39  // notified, it hasn't be run yet. We steal the lock from that fiber then
40  // to avoid potential deadlock.
41  DCHECK(threadWaiters_.empty());
42  notifiedFiber_ = nullptr;
43  return LockResult::SUCCESS;
44  }
45 
46  // Delay constructing the waiter until it is actually required.
47  // This makes a huge difference, at least in the benchmarks,
48  // when the mutex isn't locked.
49  MutexWaiter waiter;
50  if (isOnFiber) {
51  fiberWaiters_.push_back(waiter);
52  } else {
53  threadWaiters_.push_back(waiter);
54  }
55 
56  ulock.unlock();
57 
58  if (!waitFunc(waiter)) {
59  return LockResult::TIMEOUT;
60  }
61 
62  if (isOnFiber) {
63  auto lockStolen = [&] {
64  std::lock_guard<folly::SpinLock> lg(lock_);
65 
66  auto stolen = notifiedFiber_ != &waiter;
67  if (!stolen) {
68  notifiedFiber_ = nullptr;
69  }
70  return stolen;
71  }();
72 
73  if (lockStolen) {
74  return LockResult::STOLEN;
75  }
76  }
77 
78  return LockResult::SUCCESS;
79 }
folly::SpinLock lock_
Definition: TimedMutex.h:75
MutexWaiterList fiberWaiters_
Definition: TimedMutex.h:78
MutexWaiterList threadWaiters_
Definition: TimedMutex.h:77
auto ulock(Synchronized< D, M > &synchronized, Args &&...args)
MutexWaiter * notifiedFiber_
Definition: TimedMutex.h:79
TimedMutex& folly::fibers::TimedMutex::operator= ( TimedMutex &&  rhs)
delete
template<typename Rep , typename Period >
bool folly::fibers::TimedMutex::timed_lock ( const std::chrono::duration< Rep, Period > &  duration)

Definition at line 95 of file TimedMutex-inl.h.

References folly::assume_unreachable(), folly::fibers::TimedMutex::MutexWaiter::baton, folly::fibers::TimedMutex::MutexWaiter::hook, lock(), lock_, lockHelper(), STOLEN, SUCCESS, TIMEOUT, and folly::fibers::Baton::try_wait_for().

Referenced by TEST(), and ~TimedMutex().

96  {
97  auto result = lockHelper([&](MutexWaiter& waiter) {
98  if (!waiter.baton.try_wait_for(duration)) {
99  // We timed out. Two cases:
100  // 1. We're still in the waiter list and we truly timed out
101  // 2. We're not in the waiter list anymore. This could happen if the baton
102  // times out but the mutex is unlocked before we reach this code. In
103  // this
104  // case we'll pretend we got the lock on time.
105  std::lock_guard<folly::SpinLock> lg(lock_);
106  if (waiter.hook.is_linked()) {
107  waiter.hook.unlink();
108  return false;
109  }
110  }
111  return true;
112  });
113 
114  switch (result) {
115  case LockResult::SUCCESS:
116  return true;
117  case LockResult::TIMEOUT:
118  return false;
119  case LockResult::STOLEN:
120  // We don't respect the duration if lock was stolen
121  lock();
122  return true;
123  }
125 }
folly::SpinLock lock_
Definition: TimedMutex.h:75
FOLLY_ALWAYS_INLINE void assume_unreachable()
Definition: Assume.h:59
LockResult lockHelper(WaitFunc &&waitFunc)
bool folly::fibers::TimedMutex::try_lock ( )
inline

Definition at line 127 of file TimedMutex-inl.h.

References lock_, and locked_.

Referenced by ~TimedMutex().

127  {
128  std::lock_guard<folly::SpinLock> lg(lock_);
129  if (locked_) {
130  return false;
131  }
132  locked_ = true;
133  return true;
134 }
folly::SpinLock lock_
Definition: TimedMutex.h:75
void folly::fibers::TimedMutex::unlock ( )
inline

Definition at line 136 of file TimedMutex-inl.h.

References folly::fibers::TimedMutex::MutexWaiter::baton, fiberWaiters_, lock_, locked_, notifiedFiber_, folly::fibers::Baton::post(), and threadWaiters_.

Referenced by folly::fibers::TimedRWMutex< BatonType >::lock(), TEST(), and ~TimedMutex().

136  {
137  std::lock_guard<folly::SpinLock> lg(lock_);
138  if (!threadWaiters_.empty()) {
139  auto& to_wake = threadWaiters_.front();
140  threadWaiters_.pop_front();
141  to_wake.baton.post();
142  } else if (!fiberWaiters_.empty()) {
143  auto& to_wake = fiberWaiters_.front();
144  fiberWaiters_.pop_front();
145  notifiedFiber_ = &to_wake;
146  to_wake.baton.post();
147  } else {
148  locked_ = false;
149  }
150 }
folly::SpinLock lock_
Definition: TimedMutex.h:75
MutexWaiterList fiberWaiters_
Definition: TimedMutex.h:78
MutexWaiterList threadWaiters_
Definition: TimedMutex.h:77
MutexWaiter * notifiedFiber_
Definition: TimedMutex.h:79

Member Data Documentation

MutexWaiterList folly::fibers::TimedMutex::fiberWaiters_
private

Definition at line 78 of file TimedMutex.h.

Referenced by lockHelper(), unlock(), and ~TimedMutex().

bool folly::fibers::TimedMutex::locked_ = false
private

Definition at line 76 of file TimedMutex.h.

Referenced by lockHelper(), try_lock(), and unlock().

MutexWaiter* folly::fibers::TimedMutex::notifiedFiber_ {nullptr}
private

Definition at line 79 of file TimedMutex.h.

Referenced by lockHelper(), unlock(), and ~TimedMutex().

MutexWaiterList folly::fibers::TimedMutex::threadWaiters_
private

Definition at line 77 of file TimedMutex.h.

Referenced by lockHelper(), unlock(), and ~TimedMutex().


The documentation for this class was generated from the following files: