rw_spin_lock-inl.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #pragma once
  2. #ifndef RW_SPIN_LOCK_INL_H_
  3. #error "Direct inclusion of this file is not allowed, include rw_spin_lock.h"
  4. // For the sake of sane code completion.
  5. #include "rw_spin_lock.h"
  6. #endif
  7. #undef RW_SPIN_LOCK_INL_H_
  8. #include "spin_wait.h"
  9. namespace NYT::NThreading {
  10. ////////////////////////////////////////////////////////////////////////////////
  11. inline void TReaderWriterSpinLock::AcquireReader() noexcept
  12. {
  13. if (TryAcquireReader()) {
  14. return;
  15. }
  16. AcquireReaderSlow();
  17. }
  18. inline void TReaderWriterSpinLock::AcquireReaderForkFriendly() noexcept
  19. {
  20. if (TryAcquireReaderForkFriendly()) {
  21. return;
  22. }
  23. AcquireReaderForkFriendlySlow();
  24. }
  25. inline void TReaderWriterSpinLock::ReleaseReader() noexcept
  26. {
  27. auto prevValue = Value_.fetch_sub(ReaderDelta, std::memory_order::release);
  28. Y_ASSERT((prevValue & ~WriterMask) != 0);
  29. NDetail::RecordSpinLockReleased();
  30. }
  31. inline void TReaderWriterSpinLock::AcquireWriter() noexcept
  32. {
  33. if (TryAcquireWriter()) {
  34. return;
  35. }
  36. AcquireWriterSlow();
  37. }
  38. inline void TReaderWriterSpinLock::ReleaseWriter() noexcept
  39. {
  40. auto prevValue = Value_.fetch_and(~WriterMask, std::memory_order::release);
  41. Y_ASSERT(prevValue & WriterMask);
  42. NDetail::RecordSpinLockReleased();
  43. }
  44. inline bool TReaderWriterSpinLock::IsLocked() const noexcept
  45. {
  46. return Value_.load() != UnlockedValue;
  47. }
  48. inline bool TReaderWriterSpinLock::IsLockedByReader() const noexcept
  49. {
  50. return Value_.load() >= ReaderDelta;
  51. }
  52. inline bool TReaderWriterSpinLock::IsLockedByWriter() const noexcept
  53. {
  54. return (Value_.load() & WriterMask) != 0;
  55. }
  56. inline bool TReaderWriterSpinLock::TryAcquireReader() noexcept
  57. {
  58. auto oldValue = Value_.fetch_add(ReaderDelta, std::memory_order::acquire);
  59. if ((oldValue & WriterMask) != 0) {
  60. Value_.fetch_sub(ReaderDelta, std::memory_order::relaxed);
  61. return false;
  62. }
  63. NDetail::RecordSpinLockAcquired();
  64. return true;
  65. }
  66. inline bool TReaderWriterSpinLock::TryAndTryAcquireReader() noexcept
  67. {
  68. auto oldValue = Value_.load(std::memory_order::relaxed);
  69. if ((oldValue & WriterMask) != 0) {
  70. return false;
  71. }
  72. return TryAcquireReader();
  73. }
  74. inline bool TReaderWriterSpinLock::TryAcquireReaderForkFriendly() noexcept
  75. {
  76. auto oldValue = Value_.load(std::memory_order::relaxed);
  77. if ((oldValue & WriterMask) != 0) {
  78. return false;
  79. }
  80. auto newValue = oldValue + ReaderDelta;
  81. bool acquired = Value_.compare_exchange_weak(oldValue, newValue, std::memory_order::acquire);
  82. NDetail::RecordSpinLockAcquired(acquired);
  83. return acquired;
  84. }
  85. inline bool TReaderWriterSpinLock::TryAcquireWriter() noexcept
  86. {
  87. auto expected = UnlockedValue;
  88. bool acquired = Value_.compare_exchange_weak(expected, WriterMask, std::memory_order::acquire);
  89. NDetail::RecordSpinLockAcquired(acquired);
  90. return acquired;
  91. }
  92. inline bool TReaderWriterSpinLock::TryAndTryAcquireWriter() noexcept
  93. {
  94. auto oldValue = Value_.load(std::memory_order::relaxed);
  95. if (oldValue != UnlockedValue) {
  96. return false;
  97. }
  98. return TryAcquireWriter();
  99. }
  100. ////////////////////////////////////////////////////////////////////////////////
  101. template <class T>
  102. void TReaderSpinlockTraits<T>::Acquire(T* spinlock)
  103. {
  104. spinlock->AcquireReader();
  105. }
  106. template <class T>
  107. void TReaderSpinlockTraits<T>::Release(T* spinlock)
  108. {
  109. spinlock->ReleaseReader();
  110. }
  111. ////////////////////////////////////////////////////////////////////////////////
  112. template <class T>
  113. void TForkFriendlyReaderSpinlockTraits<T>::Acquire(T* spinlock)
  114. {
  115. spinlock->AcquireReaderForkFriendly();
  116. }
  117. template <class T>
  118. void TForkFriendlyReaderSpinlockTraits<T>::Release(T* spinlock)
  119. {
  120. spinlock->ReleaseReader();
  121. }
  122. ////////////////////////////////////////////////////////////////////////////////
  123. template <class T>
  124. void TWriterSpinlockTraits<T>::Acquire(T* spinlock)
  125. {
  126. spinlock->AcquireWriter();
  127. }
  128. template <class T>
  129. void TWriterSpinlockTraits<T>::Release(T* spinlock)
  130. {
  131. spinlock->ReleaseWriter();
  132. }
  133. ////////////////////////////////////////////////////////////////////////////////
  134. template <class T>
  135. auto ReaderGuard(const T& lock)
  136. {
  137. return TReaderGuard<T>(lock);
  138. }
  139. template <class T>
  140. auto ReaderGuard(const T* lock)
  141. {
  142. return TReaderGuard<T>(lock);
  143. }
  144. template <class T>
  145. auto ForkFriendlyReaderGuard(const T& lock)
  146. {
  147. return TGuard<T, TForkFriendlyReaderSpinlockTraits<T>>(lock);
  148. }
  149. template <class T>
  150. auto ForkFriendlyReaderGuard(const T* lock)
  151. {
  152. return TGuard<T, TForkFriendlyReaderSpinlockTraits<T>>(lock);
  153. }
  154. template <class T>
  155. auto WriterGuard(const T& lock)
  156. {
  157. return TWriterGuard<T>(lock);
  158. }
  159. template <class T>
  160. auto WriterGuard(const T* lock)
  161. {
  162. return TWriterGuard<T>(lock);
  163. }
  164. ////////////////////////////////////////////////////////////////////////////////
  165. } // namespace NYT::NThreading