guard.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #pragma once
  2. #include <util/generic/noncopyable.h>
  3. #include <util/system/defaults.h>
  4. template <class T>
  5. struct TCommonLockOps {
  6. static inline void Acquire(T* t) noexcept {
  7. t->Acquire();
  8. }
  9. static inline void Release(T* t) noexcept {
  10. t->Release();
  11. }
  12. };
  13. template <class T>
  14. struct TTryLockOps: public TCommonLockOps<T> {
  15. static inline bool TryAcquire(T* t) noexcept {
  16. return t->TryAcquire();
  17. }
  18. };
  19. // must be used with great care
  20. template <class TOps>
  21. struct TInverseLockOps: public TOps {
  22. template <class T>
  23. static inline void Acquire(T* t) noexcept {
  24. TOps::Release(t);
  25. }
  26. template <class T>
  27. static inline void Release(T* t) noexcept {
  28. TOps::Acquire(t);
  29. }
  30. };
  31. template <class T, class TOps = TCommonLockOps<T>>
  32. class TGuard: public TNonCopyable {
  33. public:
  34. inline TGuard(const T& t) noexcept {
  35. Init(&t);
  36. }
  37. inline TGuard(const T* t) noexcept {
  38. Init(t);
  39. }
  40. inline TGuard(TGuard&& g) noexcept
  41. : T_(g.T_)
  42. {
  43. g.T_ = nullptr;
  44. }
  45. inline ~TGuard() {
  46. Release();
  47. }
  48. inline void Release() noexcept {
  49. if (WasAcquired()) {
  50. TOps::Release(T_);
  51. T_ = nullptr;
  52. }
  53. }
  54. explicit inline operator bool() const noexcept {
  55. return WasAcquired();
  56. }
  57. inline bool WasAcquired() const noexcept {
  58. return T_ != nullptr;
  59. }
  60. inline T* GetMutex() const noexcept {
  61. return T_;
  62. }
  63. private:
  64. inline void Init(const T* t) noexcept {
  65. T_ = const_cast<T*>(t);
  66. TOps::Acquire(T_);
  67. }
  68. private:
  69. T* T_;
  70. };
  71. /*
  72. * {
  73. * auto guard = Guard(Lock_);
  74. * some code under guard
  75. * }
  76. */
  77. template <class T>
  78. static inline TGuard<T> Guard(const T& t) {
  79. return {&t};
  80. }
  81. /*
  82. * with_lock (Lock_) {
  83. * some code under guard
  84. * }
  85. */
  86. #define with_lock(X) \
  87. if (auto Y_GENERATE_UNIQUE_ID(__guard) = ::Guard(X); false) { \
  88. } else
  89. /*
  90. * auto guard = Guard(Lock_);
  91. * ... some code under lock
  92. * {
  93. * auto unguard = Unguard(guard);
  94. * ... some code not under lock
  95. * }
  96. * ... some code under lock
  97. */
  98. template <class T, class TOps = TCommonLockOps<T>>
  99. using TInverseGuard = TGuard<T, TInverseLockOps<TOps>>;
  100. template <class T, class TOps>
  101. static inline TInverseGuard<T, TOps> Unguard(const TGuard<T, TOps>& guard) {
  102. return {guard.GetMutex()};
  103. }
  104. template <class T>
  105. static inline TInverseGuard<T> Unguard(const T& mutex) {
  106. return {&mutex};
  107. }
  108. template <class T, class TOps = TTryLockOps<T>>
  109. class TTryGuard: public TNonCopyable {
  110. public:
  111. inline TTryGuard(const T& t) noexcept {
  112. Init(&t);
  113. }
  114. inline TTryGuard(const T* t) noexcept {
  115. Init(t);
  116. }
  117. inline TTryGuard(TTryGuard&& g) noexcept
  118. : T_(g.T_)
  119. {
  120. g.T_ = nullptr;
  121. }
  122. inline ~TTryGuard() {
  123. Release();
  124. }
  125. inline void Release() noexcept {
  126. if (WasAcquired()) {
  127. TOps::Release(T_);
  128. T_ = nullptr;
  129. }
  130. }
  131. inline bool WasAcquired() const noexcept {
  132. return T_ != nullptr;
  133. }
  134. explicit inline operator bool() const noexcept {
  135. return WasAcquired();
  136. }
  137. private:
  138. inline void Init(const T* t) noexcept {
  139. T_ = nullptr;
  140. T* tMutable = const_cast<T*>(t);
  141. if (TOps::TryAcquire(tMutable)) {
  142. T_ = tMutable;
  143. }
  144. }
  145. private:
  146. T* T_;
  147. };