proxygen
folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > Class Template Reference

#include <SharedMutex.h>

Classes

class  ReadHolder
 
class  UpgradeHolder
 
struct  WaitForDuration
 
struct  WaitForever
 
struct  WaitNever
 
struct  WaitUntilDeadline
 
class  WriteHolder
 

Public Types

typedef Tag_ Tag
 
typedef SharedMutexToken Token
 
typedef Atom< uintptr_t > DeferredReaderSlot
 

Public Member Functions

constexpr SharedMutexImpl () noexcept
 
 SharedMutexImpl (const SharedMutexImpl &)=delete
 
 SharedMutexImpl (SharedMutexImpl &&)=delete
 
SharedMutexImploperator= (const SharedMutexImpl &)=delete
 
SharedMutexImploperator= (SharedMutexImpl &&)=delete
 
 ~SharedMutexImpl ()
 
void lock ()
 
bool try_lock ()
 
template<class Rep , class Period >
bool try_lock_for (const std::chrono::duration< Rep, Period > &duration)
 
template<class Clock , class Duration >
bool try_lock_until (const std::chrono::time_point< Clock, Duration > &absDeadline)
 
void unlock ()
 
void lock_shared ()
 
void lock_shared (Token &token)
 
bool try_lock_shared ()
 
bool try_lock_shared (Token &token)
 
template<class Rep , class Period >
bool try_lock_shared_for (const std::chrono::duration< Rep, Period > &duration)
 
template<class Rep , class Period >
bool try_lock_shared_for (const std::chrono::duration< Rep, Period > &duration, Token &token)
 
template<class Clock , class Duration >
bool try_lock_shared_until (const std::chrono::time_point< Clock, Duration > &absDeadline)
 
template<class Clock , class Duration >
bool try_lock_shared_until (const std::chrono::time_point< Clock, Duration > &absDeadline, Token &token)
 
void unlock_shared ()
 
void unlock_shared (Token &token)
 
void unlock_and_lock_shared ()
 
void unlock_and_lock_shared (Token &token)
 
void lock_upgrade ()
 
bool try_lock_upgrade ()
 
template<class Rep , class Period >
bool try_lock_upgrade_for (const std::chrono::duration< Rep, Period > &duration)
 
template<class Clock , class Duration >
bool try_lock_upgrade_until (const std::chrono::time_point< Clock, Duration > &absDeadline)
 
void unlock_upgrade ()
 
void unlock_upgrade_and_lock ()
 
void unlock_upgrade_and_lock_shared ()
 
void unlock_upgrade_and_lock_shared (Token &token)
 
void unlock_and_lock_upgrade ()
 

Static Public Attributes

static constexpr bool kReaderPriority = ReaderPriority
 
static constexpr uint32_t kMaxDeferredReaders = 64
 
static constexpr uint32_t kDeferredSearchDistance = 2
 
static constexpr uint32_t kDeferredSeparationFactor = 4
 

Private Types

typedef folly::detail::Futex< AtomFutex
 

Private Member Functions

void annotateLazyCreate ()
 
void annotateDestroy ()
 
void annotateAcquired (annotate_rwlock_level w)
 
void annotateTryAcquired (bool result, annotate_rwlock_level w)
 
void annotateReleased (annotate_rwlock_level w)
 
template<class WaitContext >
bool lockExclusiveImpl (uint32_t preconditionGoalMask, WaitContext &ctx)
 
template<class WaitContext >
bool lockExclusiveImpl (uint32_t &state, uint32_t preconditionGoalMask, WaitContext &ctx)
 
template<class WaitContext >
bool waitForZeroBits (uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
 
template<class WaitContext >
bool yieldWaitForZeroBits (uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
 
template<class WaitContext >
bool futexWaitForZeroBits (uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
 
void wakeRegisteredWaiters (uint32_t &state, uint32_t wakeMask)
 
void wakeRegisteredWaitersImpl (uint32_t &state, uint32_t wakeMask)
 
void futexWakeAll (uint32_t wakeMask)
 
DeferredReaderSlotdeferredReader (uint32_t slot)
 
uintptr_t tokenfulSlotValue ()
 
uintptr_t tokenlessSlotValue ()
 
bool slotValueIsThis (uintptr_t slotValue)
 
template<class WaitContext >
void applyDeferredReaders (uint32_t &state, WaitContext &ctx)
 
template<class WaitContext >
void applyDeferredReaders (uint32_t &state, WaitContext &ctx, uint32_t slot)
 
template<class WaitContext >
bool lockSharedImpl (Token *token, WaitContext &ctx)
 
template<class WaitContext >
bool lockSharedImpl (uint32_t &state, Token *token, WaitContext &ctx)
 
void cleanupTokenlessSharedDeferred (uint32_t &state)
 
bool tryUnlockTokenlessSharedDeferred ()
 
bool tryUnlockSharedDeferred (uint32_t slot)
 
uint32_t unlockSharedInline ()
 
template<class WaitContext >
bool lockUpgradeImpl (WaitContext &ctx)
 

Private Attributes

Futex state_ {}
 

Static Private Attributes

static constexpr uint32_t kIncrHasS = 1 << 11
 
static constexpr uint32_t kHasS = ~(kIncrHasS - 1)
 
static constexpr uint32_t kAnnotationCreated = 1 << 10
 
static constexpr uint32_t kMayDefer = 1 << 9
 
static constexpr uint32_t kPrevDefer = 1 << 8
 
static constexpr uint32_t kHasE = 1 << 7
 
static constexpr uint32_t kBegunE = 1 << 6
 
static constexpr uint32_t kHasU = 1 << 5
 
static constexpr uint32_t kHasSolo = kHasE | kBegunE | kHasU
 
static constexpr uint32_t kWaitingNotS = 1 << 4
 
static constexpr uint32_t kWaitingESingle = 1 << 2
 
static constexpr uint32_t kWaitingEMultiple = 1 << 3
 
static constexpr uint32_t kWaitingE = kWaitingESingle | kWaitingEMultiple
 
static constexpr uint32_t kWaitingU = 1 << 1
 
static constexpr uint32_t kWaitingS = 1 << 0
 
static constexpr uint32_t kWaitingAny
 
static constexpr uint32_t kNumSharedToStartDeferring = 2
 
static constexpr uint32_t kMaxSpinCount = !BlockImmediately ? 1000 : 2
 
static constexpr uint32_t kMaxSoftYieldCount = !BlockImmediately ? 1000 : 0
 
static constexpr uint32_t kTokenStackTLSCapacity = 2
 
static constexpr uintptr_t kTokenless = 0x1
 
static FOLLY_TLS uint32_t tls_lastTokenlessSlot = 0
 
static FOLLY_TLS uint32_t tls_lastDeferredReaderSlot = 0
 
static DeferredReaderSlot deferredReaders [kMaxDeferredReaders *kDeferredSeparationFactor] = {}
 

Friends

void acquireRead (SharedMutexImpl &lock)
 
void acquireReadWrite (SharedMutexImpl &lock)
 
void releaseRead (SharedMutexImpl &lock)
 
void releaseReadWrite (SharedMutexImpl &lock)
 
bool acquireRead (SharedMutexImpl &lock, unsigned int ms)
 
bool acquireReadWrite (SharedMutexImpl &lock, unsigned int ms)
 

Detailed Description

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
class folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >

Definition at line 273 of file SharedMutex.h.

Member Typedef Documentation

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
typedef Atom<uintptr_t> folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::DeferredReaderSlot

Definition at line 892 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
typedef folly::detail::Futex<Atom> folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::Futex
private

Definition at line 572 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
typedef Tag_ folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::Tag

Definition at line 277 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
typedef SharedMutexToken folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::Token

Definition at line 279 of file SharedMutex.h.

Constructor & Destructor Documentation

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::SharedMutexImpl ( )
inlinenoexcept

Definition at line 285 of file SharedMutex.h.

285 : state_(0) {}
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::SharedMutexImpl ( const SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  )
delete
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::SharedMutexImpl ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &&  )
delete
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::~SharedMutexImpl ( )
inline

Definition at line 300 of file SharedMutex.h.

300  {
301  auto state = state_.load(std::memory_order_relaxed);
302  if (UNLIKELY((state & kHasS) != 0)) {
304  }
305 
306 #ifndef NDEBUG
307  // These asserts check that everybody has released the lock before it
308  // is destroyed. If you arrive here while debugging that is likely
309  // the problem. (You could also have general heap corruption.)
310 
311  // if a futexWait fails to go to sleep because the value has been
312  // changed, we don't necessarily clean up the wait bits, so it is
313  // possible they will be set here in a correct system
314  assert((state & ~(kWaitingAny | kMayDefer | kAnnotationCreated)) == 0);
315  if ((state & kMayDefer) != 0) {
316  for (uint32_t slot = 0; slot < kMaxDeferredReaders; ++slot) {
317  auto slotValue = deferredReader(slot)->load(std::memory_order_relaxed);
318  assert(!slotValueIsThis(slotValue));
319  }
320  }
321 #endif
322  annotateDestroy();
323  }
bool slotValueIsThis(uintptr_t slotValue)
Definition: SharedMutex.h:1138
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
static constexpr uint32_t kWaitingAny
Definition: SharedMutex.h:805
void cleanupTokenlessSharedDeferred(uint32_t &state)
Definition: SharedMutex.h:1255
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
#define UNLIKELY(x)
Definition: Likely.h:48
state
Definition: http_parser.c:272
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126

Member Function Documentation

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::annotateAcquired ( annotate_rwlock_level  w)
inlineprivate

Definition at line 693 of file SharedMutex.h.

693  {
694  if (AnnotateForThreadSanitizer) {
696  annotate_rwlock_acquired(this, w, __FILE__, __LINE__);
697  }
698  }
static FOLLY_ALWAYS_INLINE void annotate_rwlock_acquired(void const volatile *const addr, annotate_rwlock_level const w, char const *const f, int const l)
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::annotateDestroy ( )
inlineprivate

Definition at line 686 of file SharedMutex.h.

686  {
687  if (AnnotateForThreadSanitizer) {
689  annotate_rwlock_destroy(this, __FILE__, __LINE__);
690  }
691  }
static FOLLY_ALWAYS_INLINE void annotate_rwlock_destroy(void const volatile *const addr, char const *const f, int const l)
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::annotateLazyCreate ( )
inlineprivate

Definition at line 672 of file SharedMutex.h.

672  {
673  if (AnnotateForThreadSanitizer &&
674  (state_.load() & kAnnotationCreated) == 0) {
676  // check again
677  if ((state_.load() & kAnnotationCreated) == 0) {
678  state_.fetch_or(kAnnotationCreated);
680  &state_, sizeof(state_), "init TSAN", __FILE__, __LINE__);
681  annotate_rwlock_create(this, __FILE__, __LINE__);
682  }
683  }
684  }
static FOLLY_ALWAYS_INLINE void annotate_benign_race_sized(void const volatile *const addr, long const size, char const *const desc, char const *const f, int const l)
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
std::unique_lock< std::mutex > sharedMutexAnnotationGuard(void *ptr)
Definition: SharedMutex.cpp:25
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
static FOLLY_ALWAYS_INLINE void annotate_rwlock_create(void const volatile *const addr, char const *const f, int const l)
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::annotateReleased ( annotate_rwlock_level  w)
inlineprivate

Definition at line 707 of file SharedMutex.h.

707  {
708  if (AnnotateForThreadSanitizer) {
709  assert((state_.load() & kAnnotationCreated) != 0);
710  annotate_rwlock_released(this, w, __FILE__, __LINE__);
711  }
712  }
static FOLLY_ALWAYS_INLINE void annotate_rwlock_released(void const volatile *const addr, annotate_rwlock_level const w, char const *const f, int const l)
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::annotateTryAcquired ( bool  result,
annotate_rwlock_level  w 
)
inlineprivate

Definition at line 700 of file SharedMutex.h.

700  {
701  if (AnnotateForThreadSanitizer) {
703  annotate_rwlock_try_acquired(this, w, result, __FILE__, __LINE__);
704  }
705  }
static FOLLY_ALWAYS_INLINE void annotate_rwlock_try_acquired(void const volatile *const addr, annotate_rwlock_level const w, bool const result, char const *const f, int const l)
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::applyDeferredReaders ( uint32_t state,
WaitContext &  ctx 
)
inlineprivate

Definition at line 1147 of file SharedMutex.h.

1147  {
1148  uint32_t slot = 0;
1149 
1150  uint32_t spinCount = 0;
1151  while (true) {
1152  while (!slotValueIsThis(
1153  deferredReader(slot)->load(std::memory_order_acquire))) {
1154  if (++slot == kMaxDeferredReaders) {
1155  return;
1156  }
1157  }
1159  if (UNLIKELY(++spinCount >= kMaxSpinCount)) {
1160  applyDeferredReaders(state, ctx, slot);
1161  return;
1162  }
1163  }
1164  }
bool slotValueIsThis(uintptr_t slotValue)
Definition: SharedMutex.h:1138
def load()
Definition: deadlock.py:441
void applyDeferredReaders(uint32_t &state, WaitContext &ctx)
Definition: SharedMutex.h:1147
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
static constexpr uint32_t kMaxSpinCount
Definition: SharedMutex.h:820
#define UNLIKELY(x)
Definition: Likely.h:48
state
Definition: http_parser.c:272
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
void asm_volatile_pause()
Definition: Asm.h:37
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::applyDeferredReaders ( uint32_t state,
WaitContext &  ctx,
uint32_t  slot 
)
inlineprivate

Definition at line 1167 of file SharedMutex.h.

1167  {
1168 #ifdef RUSAGE_THREAD
1169  struct rusage usage;
1170  std::memset(&usage, 0, sizeof(usage));
1171  long before = -1;
1172 #endif
1173  for (uint32_t yieldCount = 0; yieldCount < kMaxSoftYieldCount;
1174  ++yieldCount) {
1175  for (int softState = 0; softState < 3; ++softState) {
1176  if (softState < 2) {
1178  } else {
1179 #ifdef RUSAGE_THREAD
1180  getrusage(RUSAGE_THREAD, &usage);
1181 #endif
1182  }
1183  while (!slotValueIsThis(
1184  deferredReader(slot)->load(std::memory_order_acquire))) {
1185  if (++slot == kMaxDeferredReaders) {
1186  return;
1187  }
1188  }
1189  if (ctx.shouldTimeOut()) {
1190  // finish applying immediately on timeout
1191  break;
1192  }
1193  }
1194 #ifdef RUSAGE_THREAD
1195  if (before >= 0 && usage.ru_nivcsw >= before + 2) {
1196  // heuristic says run queue is not empty
1197  break;
1198  }
1199  before = usage.ru_nivcsw;
1200 #endif
1201  }
1202 
1203  uint32_t movedSlotCount = 0;
1204  for (; slot < kMaxDeferredReaders; ++slot) {
1205  auto slotPtr = deferredReader(slot);
1206  auto slotValue = slotPtr->load(std::memory_order_acquire);
1207  if (slotValueIsThis(slotValue) &&
1208  slotPtr->compare_exchange_strong(slotValue, 0)) {
1209  ++movedSlotCount;
1210  }
1211  }
1212 
1213  if (movedSlotCount > 0) {
1214  state = (state_ += movedSlotCount * kIncrHasS);
1215  }
1216  assert((state & (kHasE | kBegunE)) != 0);
1217 
1218  // if state + kIncrHasS overflows (off the end of state) then either
1219  // we have 2^(32-9) readers (almost certainly an application bug)
1220  // or we had an underflow (also a bug)
1221  assert(state < state + kIncrHasS);
1222  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
bool slotValueIsThis(uintptr_t slotValue)
Definition: SharedMutex.h:1138
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kBegunE
Definition: SharedMutex.h:755
def load()
Definition: deadlock.py:441
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
static constexpr uint32_t kMaxSoftYieldCount
Definition: SharedMutex.h:828
state
Definition: http_parser.c:272
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::cleanupTokenlessSharedDeferred ( uint32_t state)
inlineprivate

Definition at line 1255 of file SharedMutex.h.

1255  {
1256  for (uint32_t i = 0; i < kMaxDeferredReaders; ++i) {
1257  auto slotPtr = deferredReader(i);
1258  auto slotValue = slotPtr->load(std::memory_order_relaxed);
1259  if (slotValue == tokenlessSlotValue()) {
1260  slotPtr->store(0, std::memory_order_relaxed);
1261  state += kIncrHasS;
1262  if ((state & kHasS) == 0) {
1263  break;
1264  }
1265  }
1266  }
1267  }
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
uintptr_t tokenlessSlotValue()
Definition: SharedMutex.h:1134
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
state
Definition: http_parser.c:272
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
DeferredReaderSlot* folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::deferredReader ( uint32_t  slot)
inlineprivate

Definition at line 1126 of file SharedMutex.h.

1126  {
1128  }
static DeferredReaderSlot deferredReaders[kMaxDeferredReaders *kDeferredSeparationFactor]
Definition: SharedMutex.h:896
static constexpr uint32_t kDeferredSeparationFactor
Definition: SharedMutex.h:853
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::futexWaitForZeroBits ( uint32_t state,
uint32_t  goal,
uint32_t  waitMask,
WaitContext &  ctx 
)
inlineprivate

Definition at line 1043 of file SharedMutex.h.

1047  {
1048  assert(
1049  waitMask == kWaitingNotS || waitMask == kWaitingE ||
1050  waitMask == kWaitingU || waitMask == kWaitingS);
1051 
1052  while (true) {
1053  state = state_.load(std::memory_order_acquire);
1054  if ((state & goal) == 0) {
1055  return true;
1056  }
1057 
1058  auto after = state;
1059  if (waitMask == kWaitingE) {
1060  if ((state & kWaitingESingle) != 0) {
1061  after |= kWaitingEMultiple;
1062  } else {
1063  after |= kWaitingESingle;
1064  }
1065  } else {
1066  after |= waitMask;
1067  }
1068 
1069  // CAS is better than atomic |= here, because it lets us avoid
1070  // setting the wait flag when the goal is concurrently achieved
1071  if (after != state && !state_.compare_exchange_strong(state, after)) {
1072  continue;
1073  }
1074 
1075  if (!ctx.doWait(state_, after, waitMask)) {
1076  // timed out
1077  return false;
1078  }
1079  }
1080  }
static constexpr uint32_t kWaitingEMultiple
Definition: SharedMutex.h:791
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
static constexpr uint32_t kWaitingESingle
Definition: SharedMutex.h:790
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::futexWakeAll ( uint32_t  wakeMask)
inlineprivate

Definition at line 1122 of file SharedMutex.h.

1122  {
1124  }
LogLevel max
Definition: LogLevel.cpp:31
int futexWake(const Futex *futex, int count, uint32_t wakeMask)
Definition: Futex-inl.h:107
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lock ( )
inline

Definition at line 325 of file SharedMutex.h.

Referenced by folly::ThreadLocalPtr< T, Tag, AccessMode >::Accessor::Accessor(), BENCHMARK(), and TEST().

325  {
326  WaitForever ctx;
327  (void)lockExclusiveImpl(kHasSolo, ctx);
329  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lock_shared ( )
inline

Definition at line 367 of file SharedMutex.h.

Referenced by BENCHMARK(), and TEST().

367  {
368  WaitForever ctx;
369  (void)lockSharedImpl(nullptr, ctx);
371  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lock_shared ( Token token)
inline

Definition at line 373 of file SharedMutex.h.

373  {
374  WaitForever ctx;
375  (void)lockSharedImpl(&token, ctx);
377  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lock_upgrade ( )
inline

Definition at line 490 of file SharedMutex.h.

490  {
491  WaitForever ctx;
492  (void)lockUpgradeImpl(ctx);
493  // For TSAN: treat upgrade locks as equivalent to read locks
495  }
bool lockUpgradeImpl(WaitContext &ctx)
Definition: SharedMutex.h:1291
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lockExclusiveImpl ( uint32_t  preconditionGoalMask,
WaitContext &  ctx 
)
inlineprivate

Definition at line 901 of file SharedMutex.h.

901  {
902  uint32_t state = state_.load(std::memory_order_acquire);
903  if (LIKELY(
904  (state & (preconditionGoalMask | kMayDefer | kHasS)) == 0 &&
905  state_.compare_exchange_strong(state, (state | kHasE) & ~kHasU))) {
906  return true;
907  } else {
908  return lockExclusiveImpl(state, preconditionGoalMask, ctx);
909  }
910  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
#define LIKELY(x)
Definition: Likely.h:47
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lockExclusiveImpl ( uint32_t state,
uint32_t  preconditionGoalMask,
WaitContext &  ctx 
)
inlineprivate

Definition at line 913 of file SharedMutex.h.

916  {
917  while (true) {
918  if (UNLIKELY((state & preconditionGoalMask) != 0) &&
919  !waitForZeroBits(state, preconditionGoalMask, kWaitingE, ctx) &&
920  ctx.canTimeOut()) {
921  return false;
922  }
923 
924  uint32_t after = (state & kMayDefer) == 0 ? 0 : kPrevDefer;
925  if (!kReaderPriority || (state & (kMayDefer | kHasS)) == 0) {
926  // Block readers immediately, either because we are in write
927  // priority mode or because we can acquire the lock in one
928  // step. Note that if state has kHasU, then we are doing an
929  // unlock_upgrade_and_lock() and we should clear it (reader
930  // priority branch also does this).
931  after |= (state | kHasE) & ~(kHasU | kMayDefer);
932  } else {
933  after |= (state | kBegunE) & ~(kHasU | kMayDefer);
934  }
935  if (state_.compare_exchange_strong(state, after)) {
936  auto before = state;
937  state = after;
938 
939  // If we set kHasE (writer priority) then no new readers can
940  // arrive. If we set kBegunE then they can still enter, but
941  // they must be inline. Either way we need to either spin on
942  // deferredReaders[] slots, or inline them so that we can wait on
943  // kHasS to zero itself. deferredReaders[] is pointers, which on
944  // x86_64 are bigger than futex() can handle, so we inline the
945  // deferred locks instead of trying to futexWait on each slot.
946  // Readers are responsible for rechecking state_ after recording
947  // a deferred read to avoid atomicity problems between the state_
948  // CAS and applyDeferredReader's reads of deferredReaders[].
949  if (UNLIKELY((before & kMayDefer) != 0)) {
951  }
952  while (true) {
953  assert((state & (kHasE | kBegunE)) != 0 && (state & kHasU) == 0);
954  if (UNLIKELY((state & kHasS) != 0) &&
955  !waitForZeroBits(state, kHasS, kWaitingNotS, ctx) &&
956  ctx.canTimeOut()) {
957  // Ugh. We blocked new readers and other writers for a while,
958  // but were unable to complete. Move on. On the plus side
959  // we can clear kWaitingNotS because nobody else can piggyback
960  // on it.
963  return false;
964  }
965 
966  if (kReaderPriority && (state & kHasE) == 0) {
967  assert((state & kBegunE) != 0);
968  if (!state_.compare_exchange_strong(
969  state, (state & ~kBegunE) | kHasE)) {
970  continue;
971  }
972  }
973 
974  return true;
975  }
976  }
977  }
978  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void wakeRegisteredWaiters(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1085
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
static constexpr uint32_t kBegunE
Definition: SharedMutex.h:755
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
void applyDeferredReaders(uint32_t &state, WaitContext &ctx)
Definition: SharedMutex.h:1147
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
bool waitForZeroBits(uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
Definition: SharedMutex.h:981
static constexpr bool kReaderPriority
Definition: SharedMutex.h:275
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
#define UNLIKELY(x)
Definition: Likely.h:48
static constexpr uint32_t kPrevDefer
Definition: SharedMutex.h:742
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lockSharedImpl ( Token token,
WaitContext &  ctx 
)
inlineprivate

Definition at line 1238 of file SharedMutex.h.

1238  {
1239  uint32_t state = state_.load(std::memory_order_relaxed);
1240  if ((state & (kHasS | kMayDefer | kHasE)) == 0 &&
1241  state_.compare_exchange_strong(state, state + kIncrHasS)) {
1242  if (token != nullptr) {
1243  token->type_ = Token::Type::INLINE_SHARED;
1244  }
1245  return true;
1246  }
1247  return lockSharedImpl(state, token, ctx);
1248  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ , template< typename > class Atom, bool BlockImmediately, bool AnnotateForThreadSanitizer>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lockSharedImpl ( uint32_t state,
Token token,
WaitContext &  ctx 
)
private

Definition at line 1604 of file SharedMutex.h.

References i, folly::SharedMutexToken::slot_, folly::SharedMutexToken::type_, uint16_t, uint32_t, and UNLIKELY.

1604  {
1605  while (true) {
1606  if (UNLIKELY((state & kHasE) != 0) &&
1607  !waitForZeroBits(state, kHasE, kWaitingS, ctx) && ctx.canTimeOut()) {
1608  return false;
1609  }
1610 
1612  uintptr_t slotValue = 1; // any non-zero value will do
1613 
1614  bool canAlreadyDefer = (state & kMayDefer) != 0;
1615  bool aboveDeferThreshold =
1617  bool drainInProgress = ReaderPriority && (state & kBegunE) != 0;
1618  if (canAlreadyDefer || (aboveDeferThreshold && !drainInProgress)) {
1619  /* Try using the most recent slot first. */
1620  slotValue = deferredReader(slot)->load(std::memory_order_relaxed);
1621  if (slotValue != 0) {
1622  // starting point for our empty-slot search, can change after
1623  // calling waitForZeroBits
1624  uint32_t bestSlot =
1626 
1627  // deferred readers are already enabled, or it is time to
1628  // enable them if we can find a slot
1629  for (uint32_t i = 0; i < kDeferredSearchDistance; ++i) {
1630  slot = bestSlot ^ i;
1631  assert(slot < kMaxDeferredReaders);
1632  slotValue = deferredReader(slot)->load(std::memory_order_relaxed);
1633  if (slotValue == 0) {
1634  // found empty slot
1636  break;
1637  }
1638  }
1639  }
1640  }
1641 
1642  if (slotValue != 0) {
1643  // not yet deferred, or no empty slots
1644  if (state_.compare_exchange_strong(state, state + kIncrHasS)) {
1645  // successfully recorded the read lock inline
1646  if (token != nullptr) {
1647  token->type_ = Token::Type::INLINE_SHARED;
1648  }
1649  return true;
1650  }
1651  // state is updated, try again
1652  continue;
1653  }
1654 
1655  // record that deferred readers might be in use if necessary
1656  if ((state & kMayDefer) == 0) {
1657  if (!state_.compare_exchange_strong(state, state | kMayDefer)) {
1658  // keep going if CAS failed because somebody else set the bit
1659  // for us
1660  if ((state & (kHasE | kMayDefer)) != kMayDefer) {
1661  continue;
1662  }
1663  }
1664  // state = state | kMayDefer;
1665  }
1666 
1667  // try to use the slot
1668  bool gotSlot = deferredReader(slot)->compare_exchange_strong(
1669  slotValue,
1670  token == nullptr ? tokenlessSlotValue() : tokenfulSlotValue());
1671 
1672  // If we got the slot, we need to verify that an exclusive lock
1673  // didn't happen since we last checked. If we didn't get the slot we
1674  // need to recheck state_ anyway to make sure we don't waste too much
1675  // work. It is also possible that since we checked state_ someone
1676  // has acquired and released the write lock, clearing kMayDefer.
1677  // Both cases are covered by looking for the readers-possible bit,
1678  // because it is off when the exclusive lock bit is set.
1679  state = state_.load(std::memory_order_acquire);
1680 
1681  if (!gotSlot) {
1682  continue;
1683  }
1684 
1685  if (token == nullptr) {
1686  tls_lastTokenlessSlot = slot;
1687  }
1688 
1689  if ((state & kMayDefer) != 0) {
1690  assert((state & kHasE) == 0);
1691  // success
1692  if (token != nullptr) {
1693  token->type_ = Token::Type::DEFERRED_SHARED;
1694  token->slot_ = (uint16_t)slot;
1695  }
1696  return true;
1697  }
1698 
1699  // release the slot before retrying
1700  if (token == nullptr) {
1701  // We can't rely on slot. Token-less slot values can be freed by
1702  // any unlock_shared(), so we need to do the full deferredReader
1703  // search during unlock. Unlike unlock_shared(), we can't trust
1704  // kPrevDefer here. This deferred lock isn't visible to lock()
1705  // (that's the whole reason we're undoing it) so there might have
1706  // subsequently been an unlock() and lock() with no intervening
1707  // transition to deferred mode.
1710  }
1711  } else {
1712  if (!tryUnlockSharedDeferred(slot)) {
1714  }
1715  }
1716 
1717  // We got here not because the lock was unavailable, but because
1718  // we lost a compare-and-swap. Try-lock is typically allowed to
1719  // have spurious failures, but there is no lock efficiency gain
1720  // from exploiting that freedom here.
1721  }
1722 }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
static constexpr uint32_t kDeferredSearchDistance
Definition: SharedMutex.h:852
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
static FOLLY_TLS uint32_t tls_lastTokenlessSlot
Definition: SharedMutex.h:882
uintptr_t tokenlessSlotValue()
Definition: SharedMutex.h:1134
static constexpr uint32_t kBegunE
Definition: SharedMutex.h:755
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
static FOLLY_TLS uint32_t tls_lastDeferredReaderSlot
Definition: SharedMutex.h:885
uintptr_t tokenfulSlotValue()
Definition: SharedMutex.h:1130
static constexpr uint32_t kNumSharedToStartDeferring
Definition: SharedMutex.h:813
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
bool tryUnlockTokenlessSharedDeferred()
Definition: SharedMutex.h:1577
uint32_t unlockSharedInline()
Definition: SharedMutex.h:1277
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
bool waitForZeroBits(uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
Definition: SharedMutex.h:981
#define UNLIKELY(x)
Definition: Likely.h:48
bool tryUnlockSharedDeferred(uint32_t slot)
Definition: SharedMutex.h:1271
state
Definition: http_parser.c:272
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::lockUpgradeImpl ( WaitContext &  ctx)
inlineprivate

Definition at line 1291 of file SharedMutex.h.

1291  {
1292  uint32_t state;
1293  do {
1294  if (!waitForZeroBits(state, kHasSolo, kWaitingU, ctx)) {
1295  return false;
1296  }
1297  } while (!state_.compare_exchange_strong(state, state | kHasU));
1298  return true;
1299  }
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
bool waitForZeroBits(uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
Definition: SharedMutex.h:981
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
SharedMutexImpl& folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::operator= ( const SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  )
delete
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
SharedMutexImpl& folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::operator= ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &&  )
delete
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::slotValueIsThis ( uintptr_t  slotValue)
inlineprivate

Definition at line 1138 of file SharedMutex.h.

1138  {
1139  return (slotValue & ~kTokenless) == tokenfulSlotValue();
1140  }
uintptr_t tokenfulSlotValue()
Definition: SharedMutex.h:1130
static constexpr uintptr_t kTokenless
Definition: SharedMutex.h:879
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
uintptr_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tokenfulSlotValue ( )
inlineprivate

Definition at line 1130 of file SharedMutex.h.

1130  {
1131  return reinterpret_cast<uintptr_t>(this);
1132  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
uintptr_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tokenlessSlotValue ( )
inlineprivate

Definition at line 1134 of file SharedMutex.h.

1134  {
1135  return tokenfulSlotValue() | kTokenless;
1136  }
uintptr_t tokenfulSlotValue()
Definition: SharedMutex.h:1130
static constexpr uintptr_t kTokenless
Definition: SharedMutex.h:879
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock ( )
inline

Definition at line 331 of file SharedMutex.h.

331  {
332  WaitNever ctx;
333  auto result = lockExclusiveImpl(kHasSolo, ctx);
335  return result;
336  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Rep , class Period >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_for ( const std::chrono::duration< Rep, Period > &  duration)
inline

Definition at line 339 of file SharedMutex.h.

339  {
340  WaitForDuration<Rep, Period> ctx(duration);
341  auto result = lockExclusiveImpl(kHasSolo, ctx);
343  return result;
344  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared ( )
inline

Definition at line 379 of file SharedMutex.h.

Referenced by TEST().

379  {
380  WaitNever ctx;
381  auto result = lockSharedImpl(nullptr, ctx);
383  return result;
384  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared ( Token token)
inline

Definition at line 386 of file SharedMutex.h.

386  {
387  WaitNever ctx;
388  auto result = lockSharedImpl(&token, ctx);
390  return result;
391  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Rep , class Period >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared_for ( const std::chrono::duration< Rep, Period > &  duration)
inline

Definition at line 394 of file SharedMutex.h.

394  {
395  WaitForDuration<Rep, Period> ctx(duration);
396  auto result = lockSharedImpl(nullptr, ctx);
398  return result;
399  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Rep , class Period >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared_for ( const std::chrono::duration< Rep, Period > &  duration,
Token token 
)
inline

Definition at line 402 of file SharedMutex.h.

404  {
405  WaitForDuration<Rep, Period> ctx(duration);
406  auto result = lockSharedImpl(&token, ctx);
408  return result;
409  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Clock , class Duration >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared_until ( const std::chrono::time_point< Clock, Duration > &  absDeadline)
inline

Definition at line 412 of file SharedMutex.h.

413  {
414  WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
415  auto result = lockSharedImpl(nullptr, ctx);
417  return result;
418  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Clock , class Duration >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_shared_until ( const std::chrono::time_point< Clock, Duration > &  absDeadline,
Token token 
)
inline

Definition at line 421 of file SharedMutex.h.

423  {
424  WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
425  auto result = lockSharedImpl(&token, ctx);
427  return result;
428  }
bool lockSharedImpl(Token *token, WaitContext &ctx)
Definition: SharedMutex.h:1238
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Clock , class Duration >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_until ( const std::chrono::time_point< Clock, Duration > &  absDeadline)
inline

Definition at line 347 of file SharedMutex.h.

348  {
349  WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
350  auto result = lockExclusiveImpl(kHasSolo, ctx);
352  return result;
353  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_upgrade ( )
inline

Definition at line 497 of file SharedMutex.h.

Referenced by TEST().

497  {
498  WaitNever ctx;
499  auto result = lockUpgradeImpl(ctx);
501  return result;
502  }
bool lockUpgradeImpl(WaitContext &ctx)
Definition: SharedMutex.h:1291
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Rep , class Period >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_upgrade_for ( const std::chrono::duration< Rep, Period > &  duration)
inline

Definition at line 505 of file SharedMutex.h.

506  {
507  WaitForDuration<Rep, Period> ctx(duration);
508  auto result = lockUpgradeImpl(ctx);
510  return result;
511  }
bool lockUpgradeImpl(WaitContext &ctx)
Definition: SharedMutex.h:1291
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class Clock , class Duration >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::try_lock_upgrade_until ( const std::chrono::time_point< Clock, Duration > &  absDeadline)
inline

Definition at line 514 of file SharedMutex.h.

515  {
516  WaitUntilDeadline<Clock, Duration> ctx{absDeadline};
517  auto result = lockUpgradeImpl(ctx);
519  return result;
520  }
bool lockUpgradeImpl(WaitContext &ctx)
Definition: SharedMutex.h:1291
void annotateTryAcquired(bool result, annotate_rwlock_level w)
Definition: SharedMutex.h:700
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tryUnlockSharedDeferred ( uint32_t  slot)
inlineprivate

Definition at line 1271 of file SharedMutex.h.

1271  {
1272  assert(slot < kMaxDeferredReaders);
1273  auto slotValue = tokenfulSlotValue();
1274  return deferredReader(slot)->compare_exchange_strong(slotValue, 0);
1275  }
uintptr_t tokenfulSlotValue()
Definition: SharedMutex.h:1130
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
template<bool ReaderPriority, typename Tag_ , template< typename > class Atom, bool BlockImmediately, bool AnnotateForThreadSanitizer>
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tryUnlockTokenlessSharedDeferred ( )
private

Definition at line 1577 of file SharedMutex.h.

References Atom, i, and uint32_t.

1577  {
1578  auto bestSlot = tls_lastTokenlessSlot;
1579  for (uint32_t i = 0; i < kMaxDeferredReaders; ++i) {
1580  auto slotPtr = deferredReader(bestSlot ^ i);
1581  auto slotValue = slotPtr->load(std::memory_order_relaxed);
1582  if (slotValue == tokenlessSlotValue() &&
1583  slotPtr->compare_exchange_strong(slotValue, 0)) {
1584  tls_lastTokenlessSlot = bestSlot ^ i;
1585  return true;
1586  }
1587  }
1588  return false;
1589 }
static FOLLY_TLS uint32_t tls_lastTokenlessSlot
Definition: SharedMutex.h:882
uintptr_t tokenlessSlotValue()
Definition: SharedMutex.h:1134
static constexpr uint32_t kMaxDeferredReaders
Definition: SharedMutex.h:851
DeferredReaderSlot * deferredReader(uint32_t slot)
Definition: SharedMutex.h:1126
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock ( )
inline

Definition at line 355 of file SharedMutex.h.

Referenced by BENCHMARK(), folly::ThreadLocalPtr< T, Tag, AccessMode >::Accessor::release(), and TEST().

355  {
357  // It is possible that we have a left-over kWaitingNotS if the last
358  // unlock_shared() that let our matching lock() complete finished
359  // releasing before lock()'s futexWait went to sleep. Clean it up now
360  auto state = (state_ &= ~(kWaitingNotS | kPrevDefer | kHasE));
361  assert((state & ~(kWaitingAny | kAnnotationCreated)) == 0);
363  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
void wakeRegisteredWaiters(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1085
static constexpr uint32_t kWaitingAny
Definition: SharedMutex.h:805
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
static constexpr uint32_t kPrevDefer
Definition: SharedMutex.h:742
state
Definition: http_parser.c:272
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_and_lock_shared ( )
inline

Definition at line 465 of file SharedMutex.h.

465  {
468  // We can't use state_ -=, because we need to clear 2 bits (1 of which
469  // has an uncertain initial state) and set 1 other. We might as well
470  // clear the relevant wake bits at the same time. Note that since S
471  // doesn't block the beginning of a transition to E (writer priority
472  // can cut off new S, reader priority grabs BegunE and blocks deferred
473  // S) we need to wake E as well.
474  auto state = state_.load(std::memory_order_acquire);
475  do {
476  assert(
478  } while (!state_.compare_exchange_strong(
480  if ((state & (kWaitingE | kWaitingU | kWaitingS)) != 0) {
482  }
483  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kWaitingAny
Definition: SharedMutex.h:805
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
void futexWakeAll(uint32_t wakeMask)
Definition: SharedMutex.h:1122
static constexpr uint32_t kPrevDefer
Definition: SharedMutex.h:742
state
Definition: http_parser.c:272
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_and_lock_shared ( Token token)
inline

Definition at line 485 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_and_lock_upgrade ( )
inline

Definition at line 550 of file SharedMutex.h.

550  {
553  // We can't use state_ -=, because we need to clear 2 bits (1 of
554  // which has an uncertain initial state) and set 1 other. We might
555  // as well clear the relevant wake bits at the same time.
556  auto state = state_.load(std::memory_order_acquire);
557  while (true) {
558  assert(
560  auto after =
562  if (state_.compare_exchange_strong(state, after)) {
563  if ((state & kWaitingS) != 0) {
564  futexWakeAll(kWaitingS);
565  }
566  return;
567  }
568  }
569  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
static constexpr uint32_t kWaitingAny
Definition: SharedMutex.h:805
static constexpr uint32_t kWaitingS
Definition: SharedMutex.h:800
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
void futexWakeAll(uint32_t wakeMask)
Definition: SharedMutex.h:1122
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
static constexpr uint32_t kPrevDefer
Definition: SharedMutex.h:742
state
Definition: http_parser.c:272
static constexpr uint32_t kAnnotationCreated
Definition: SharedMutex.h:731
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_shared ( )
inline

Definition at line 430 of file SharedMutex.h.

Referenced by BENCHMARK(), and TEST().

430  {
432 
433  auto state = state_.load(std::memory_order_acquire);
434 
435  // kPrevDefer can only be set if HasE or BegunE is set
436  assert((state & (kPrevDefer | kHasE | kBegunE)) != kPrevDefer);
437 
438  // lock() strips kMayDefer immediately, but then copies it to
439  // kPrevDefer so we can tell if the pre-lock() lock_shared() might
440  // have deferred
441  if ((state & (kMayDefer | kPrevDefer)) == 0 ||
443  // Matching lock_shared() couldn't have deferred, or the deferred
444  // lock has already been inlined by applyDeferredReaders()
446  }
447  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
static constexpr uint32_t kBegunE
Definition: SharedMutex.h:755
bool tryUnlockTokenlessSharedDeferred()
Definition: SharedMutex.h:1577
uint32_t unlockSharedInline()
Definition: SharedMutex.h:1277
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
static constexpr uint32_t kPrevDefer
Definition: SharedMutex.h:742
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_shared ( Token token)
inline

Definition at line 449 of file SharedMutex.h.

449  {
451 
452  assert(
453  token.type_ == Token::Type::INLINE_SHARED ||
454  token.type_ == Token::Type::DEFERRED_SHARED);
455 
456  if (token.type_ != Token::Type::DEFERRED_SHARED ||
457  !tryUnlockSharedDeferred(token.slot_)) {
459  }
460 #ifndef NDEBUG
461  token.type_ = Token::Type::INVALID;
462 #endif
463  }
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
uint32_t unlockSharedInline()
Definition: SharedMutex.h:1277
bool tryUnlockSharedDeferred(uint32_t slot)
Definition: SharedMutex.h:1271
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_upgrade ( )
inline

Definition at line 522 of file SharedMutex.h.

Referenced by TEST().

522  {
524  auto state = (state_ -= kHasU);
525  assert((state & (kWaitingNotS | kHasSolo)) == 0);
527  }
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
void wakeRegisteredWaiters(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1085
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_upgrade_and_lock ( )
inline

Definition at line 529 of file SharedMutex.h.

529  {
530  // no waiting necessary, so waitMask is empty
531  WaitForever ctx;
532  (void)lockExclusiveImpl(0, ctx);
535  }
bool lockExclusiveImpl(uint32_t preconditionGoalMask, WaitContext &ctx)
Definition: SharedMutex.h:901
void annotateReleased(annotate_rwlock_level w)
Definition: SharedMutex.h:707
void annotateAcquired(annotate_rwlock_level w)
Definition: SharedMutex.h:693
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_upgrade_and_lock_shared ( )
inline

Definition at line 537 of file SharedMutex.h.

537  {
538  // No need to annotate for TSAN here because we model upgrade and shared
539  // locks as the same.
540  auto state = (state_ -= kHasU - kIncrHasS);
541  assert((state & (kWaitingNotS | kHasSolo)) == 0);
543  }
void wakeRegisteredWaiters(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1085
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kHasU
Definition: SharedMutex.h:765
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
static constexpr uint32_t kHasSolo
Definition: SharedMutex.h:773
static constexpr uint32_t kWaitingU
Definition: SharedMutex.h:796
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlock_upgrade_and_lock_shared ( Token token)
inline

Definition at line 545 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::unlockSharedInline ( )
inlineprivate

Definition at line 1277 of file SharedMutex.h.

1277  {
1278  uint32_t state = (state_ -= kIncrHasS);
1279  assert(
1280  (state & (kHasE | kBegunE | kMayDefer)) != 0 ||
1281  state < state + kIncrHasS);
1282  if ((state & kHasS) == 0) {
1283  // Only the second half of lock() can be blocked by a non-zero
1284  // reader count, so that's the only thing we need to wake
1286  }
1287  return state;
1288  }
static constexpr uint32_t kHasE
Definition: SharedMutex.h:748
void wakeRegisteredWaiters(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1085
static constexpr uint32_t kIncrHasS
Definition: SharedMutex.h:725
static constexpr uint32_t kHasS
Definition: SharedMutex.h:726
static constexpr uint32_t kBegunE
Definition: SharedMutex.h:755
static constexpr uint32_t kMayDefer
Definition: SharedMutex.h:735
static constexpr uint32_t kWaitingNotS
Definition: SharedMutex.h:779
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::waitForZeroBits ( uint32_t state,
uint32_t  goal,
uint32_t  waitMask,
WaitContext &  ctx 
)
inlineprivate

Definition at line 981 of file SharedMutex.h.

985  {
986  uint32_t spinCount = 0;
987  while (true) {
988  state = state_.load(std::memory_order_acquire);
989  if ((state & goal) == 0) {
990  return true;
991  }
993  ++spinCount;
994  if (UNLIKELY(spinCount >= kMaxSpinCount)) {
995  return ctx.canBlock() &&
996  yieldWaitForZeroBits(state, goal, waitMask, ctx);
997  }
998  }
999  }
bool yieldWaitForZeroBits(uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
Definition: SharedMutex.h:1002
static constexpr uint32_t kMaxSpinCount
Definition: SharedMutex.h:820
#define UNLIKELY(x)
Definition: Likely.h:48
state
Definition: http_parser.c:272
void asm_volatile_pause()
Definition: Asm.h:37
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::wakeRegisteredWaiters ( uint32_t state,
uint32_t  wakeMask 
)
inlineprivate

Definition at line 1085 of file SharedMutex.h.

1085  {
1086  if (UNLIKELY((state & wakeMask) != 0)) {
1087  wakeRegisteredWaitersImpl(state, wakeMask);
1088  }
1089  }
#define UNLIKELY(x)
Definition: Likely.h:48
void wakeRegisteredWaitersImpl(uint32_t &state, uint32_t wakeMask)
Definition: SharedMutex.h:1091
state
Definition: http_parser.c:272
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::wakeRegisteredWaitersImpl ( uint32_t state,
uint32_t  wakeMask 
)
inlineprivate

Definition at line 1091 of file SharedMutex.h.

1091  {
1092  // If there are multiple lock() pending only one of them will actually
1093  // get to wake up, so issuing futexWakeAll will make a thundering herd.
1094  // There's nothing stopping us from issuing futexWake(1) instead,
1095  // so long as the wait bits are still an accurate reflection of
1096  // the waiters. If we notice (via futexWake's return value) that
1097  // nobody woke up then we can try again with the normal wake-all path.
1098  // Note that we can't just clear the bits at that point; we need to
1099  // clear the bits and then issue another wakeup.
1100  //
1101  // It is possible that we wake an E waiter but an outside S grabs the
1102  // lock instead, at which point we should wake pending U and S waiters.
1103  // Rather than tracking state to make the failing E regenerate the
1104  // wakeup, we just disable the optimization in the case that there
1105  // are waiting U or S that we are eligible to wake.
1106  if ((wakeMask & kWaitingE) == kWaitingE &&
1107  (state & wakeMask) == kWaitingE &&
1108  detail::futexWake(&state_, 1, kWaitingE) > 0) {
1109  // somebody woke up, so leave state_ as is and clear it later
1110  return;
1111  }
1112 
1113  if ((state & wakeMask) != 0) {
1114  auto prev = state_.fetch_and(~wakeMask);
1115  if ((prev & wakeMask) != 0) {
1116  futexWakeAll(wakeMask);
1117  }
1118  state = prev & ~wakeMask;
1119  }
1120  }
static constexpr uint32_t kWaitingE
Definition: SharedMutex.h:792
void futexWakeAll(uint32_t wakeMask)
Definition: SharedMutex.h:1122
state
Definition: http_parser.c:272
int futexWake(const Futex *futex, int count, uint32_t wakeMask)
Definition: Futex-inl.h:107
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
template<class WaitContext >
bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::yieldWaitForZeroBits ( uint32_t state,
uint32_t  goal,
uint32_t  waitMask,
WaitContext &  ctx 
)
inlineprivate

Definition at line 1002 of file SharedMutex.h.

1006  {
1007 #ifdef RUSAGE_THREAD
1008  struct rusage usage;
1009  std::memset(&usage, 0, sizeof(usage));
1010  long before = -1;
1011 #endif
1012  for (uint32_t yieldCount = 0; yieldCount < kMaxSoftYieldCount;
1013  ++yieldCount) {
1014  for (int softState = 0; softState < 3; ++softState) {
1015  if (softState < 2) {
1017  } else {
1018 #ifdef RUSAGE_THREAD
1019  getrusage(RUSAGE_THREAD, &usage);
1020 #endif
1021  }
1022  if (((state = state_.load(std::memory_order_acquire)) & goal) == 0) {
1023  return true;
1024  }
1025  if (ctx.shouldTimeOut()) {
1026  return false;
1027  }
1028  }
1029 #ifdef RUSAGE_THREAD
1030  if (before >= 0 && usage.ru_nivcsw >= before + 2) {
1031  // One involuntary csw might just be occasional background work,
1032  // but if we get two in a row then we guess that there is someone
1033  // else who can profitably use this CPU. Fall back to futex
1034  break;
1035  }
1036  before = usage.ru_nivcsw;
1037 #endif
1038  }
1039  return futexWaitForZeroBits(state, goal, waitMask, ctx);
1040  }
bool futexWaitForZeroBits(uint32_t &state, uint32_t goal, uint32_t waitMask, WaitContext &ctx)
Definition: SharedMutex.h:1043
static constexpr uint32_t kMaxSoftYieldCount
Definition: SharedMutex.h:828
state
Definition: http_parser.c:272

Friends And Related Function Documentation

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void acquireRead ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock)
friend

Definition at line 1489 of file SharedMutex.h.

1489  {
1490  lock.lock_shared();
1491  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool acquireRead ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock,
unsigned int  ms 
)
friend

Definition at line 1501 of file SharedMutex.h.

1501  {
1502  return lock.try_lock_shared_for(std::chrono::milliseconds(ms));
1503  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void acquireReadWrite ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock)
friend

Definition at line 1492 of file SharedMutex.h.

1492  {
1493  lock.lock();
1494  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
bool acquireReadWrite ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock,
unsigned int  ms 
)
friend

Definition at line 1504 of file SharedMutex.h.

1504  {
1505  return lock.try_lock_for(std::chrono::milliseconds(ms));
1506  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void releaseRead ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock)
friend

Definition at line 1495 of file SharedMutex.h.

1495  {
1496  lock.unlock_shared();
1497  }
template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
void releaseReadWrite ( SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer > &  lock)
friend

Definition at line 1498 of file SharedMutex.h.

1498  {
1499  lock.unlock();
1500  }

Member Data Documentation

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::DeferredReaderSlot folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::deferredReaders = {}
staticprivate

Definition at line 896 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kAnnotationCreated = 1 << 10
staticprivate

Definition at line 731 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kBegunE = 1 << 6
staticprivate

Definition at line 755 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kDeferredSearchDistance = 2
static

Definition at line 852 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kDeferredSeparationFactor = 4
static

Definition at line 853 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kHasE = 1 << 7
staticprivate

Definition at line 748 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kHasS = ~(kIncrHasS - 1)
staticprivate

Definition at line 726 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kHasSolo = kHasE | kBegunE | kHasU
staticprivate

Definition at line 773 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kHasU = 1 << 5
staticprivate

Definition at line 765 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kIncrHasS = 1 << 11
staticprivate

Definition at line 725 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kMaxDeferredReaders = 64
static

Definition at line 851 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kMaxSoftYieldCount = !BlockImmediately ? 1000 : 0
staticprivate

Definition at line 828 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kMaxSpinCount = !BlockImmediately ? 1000 : 2
staticprivate

Definition at line 820 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kMayDefer = 1 << 9
staticprivate

Definition at line 735 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kNumSharedToStartDeferring = 2
staticprivate

Definition at line 813 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kPrevDefer = 1 << 8
staticprivate

Definition at line 742 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr bool folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kReaderPriority = ReaderPriority
static

Definition at line 275 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uintptr_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kTokenless = 0x1
staticprivate

Definition at line 879 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kTokenStackTLSCapacity = 2
staticprivate

Definition at line 868 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingAny
staticprivate
Initial value:

Definition at line 805 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingE = kWaitingESingle | kWaitingEMultiple
staticprivate

Definition at line 792 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingEMultiple = 1 << 3
staticprivate

Definition at line 791 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingESingle = 1 << 2
staticprivate

Definition at line 790 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingNotS = 1 << 4
staticprivate

Definition at line 779 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingS = 1 << 0
staticprivate

Definition at line 800 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
constexpr uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::kWaitingU = 1 << 1
staticprivate

Definition at line 796 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
Futex folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::state_ {}
private

Definition at line 715 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
FOLLY_TLS uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tls_lastDeferredReaderSlot = 0
staticprivate

Definition at line 885 of file SharedMutex.h.

template<bool ReaderPriority, typename Tag_ = void, template< typename > class Atom = std::atomic, bool BlockImmediately = false, bool AnnotateForThreadSanitizer = kIsSanitizeThread && !ReaderPriority>
FOLLY_TLS uint32_t folly::SharedMutexImpl< ReaderPriority, Tag_, Atom, BlockImmediately, AnnotateForThreadSanitizer >::tls_lastTokenlessSlot = 0
staticprivate

Definition at line 882 of file SharedMutex.h.


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