recursive_spin_lock-inl.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #ifndef RECURSIVE_SPIN_LOCK_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include recursive_spinlock.h"
  3. // For the sake of sane code completion.
  4. #include "recursive_spin_lock.h"
  5. #endif
  6. #undef RECURSIVE_SPIN_LOCK_INL_H_
  7. #include "spin_wait.h"
  8. #include <library/cpp/yt/assert/assert.h>
  9. namespace NYT::NThreading {
  10. ////////////////////////////////////////////////////////////////////////////////
  11. inline void TRecursiveSpinLock::Acquire() noexcept
  12. {
  13. if (TryAcquire()) {
  14. return;
  15. }
  16. AcquireSlow();
  17. }
  18. inline bool TRecursiveSpinLock::TryAcquire() noexcept
  19. {
  20. auto currentThreadId = GetSequentialThreadId();
  21. auto oldValue = Value_.load();
  22. auto oldRecursionDepth = oldValue & RecursionDepthMask;
  23. if (oldRecursionDepth > 0 && (oldValue >> ThreadIdShift) != currentThreadId) {
  24. return false;
  25. }
  26. auto newValue = (oldRecursionDepth + 1) | (static_cast<TValue>(currentThreadId) << ThreadIdShift);
  27. bool acquired = Value_.compare_exchange_weak(oldValue, newValue);
  28. NDetail::RecordSpinLockAcquired(acquired);
  29. return acquired;
  30. }
  31. inline void TRecursiveSpinLock::Release() noexcept
  32. {
  33. #ifndef NDEBUG
  34. auto value = Value_.load();
  35. YT_ASSERT((value & RecursionDepthMask) > 0);
  36. YT_ASSERT((value >> ThreadIdShift) == GetSequentialThreadId());
  37. #endif
  38. --Value_;
  39. NDetail::RecordSpinLockReleased();
  40. }
  41. inline bool TRecursiveSpinLock::IsLocked() const noexcept
  42. {
  43. auto value = Value_.load();
  44. return (value & RecursionDepthMask) > 0;
  45. }
  46. inline bool TRecursiveSpinLock::IsLockedByCurrentThread() const noexcept
  47. {
  48. auto value = Value_.load();
  49. return (value & RecursionDepthMask) > 0 && (value >> ThreadIdShift) == GetSequentialThreadId();
  50. }
  51. inline bool TRecursiveSpinLock::TryAndTryAcquire() noexcept
  52. {
  53. auto value = Value_.load(std::memory_order::relaxed);
  54. auto recursionDepth = value & RecursionDepthMask;
  55. if (recursionDepth > 0 && (value >> ThreadIdShift) != GetSequentialThreadId()) {
  56. return false;
  57. }
  58. return TryAcquire();
  59. }
  60. ////////////////////////////////////////////////////////////////////////////////
  61. } // namespace NYT::NThreading