guard.h 3.4 KB

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