123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- #pragma once
- #include <util/generic/noncopyable.h>
- #include <util/system/defaults.h>
- template <class T>
- struct TCommonLockOps {
- static inline void Acquire(T* t) noexcept {
- t->Acquire();
- }
- static inline void Release(T* t) noexcept {
- t->Release();
- }
- };
- template <class T>
- struct TTryLockOps: public TCommonLockOps<T> {
- static inline bool TryAcquire(T* t) noexcept {
- return t->TryAcquire();
- }
- };
- // must be used with great care
- template <class TOps>
- struct TInverseLockOps: public TOps {
- template <class T>
- static inline void Acquire(T* t) noexcept {
- TOps::Release(t);
- }
- template <class T>
- static inline void Release(T* t) noexcept {
- TOps::Acquire(t);
- }
- };
- template <class T, class TOps = TCommonLockOps<T>>
- class TGuard: public TNonCopyable {
- public:
- inline TGuard(const T& t) noexcept {
- Init(&t);
- }
- inline TGuard(const T* t) noexcept {
- Init(t);
- }
- inline TGuard(TGuard&& g) noexcept
- : T_(g.T_)
- {
- g.T_ = nullptr;
- }
- inline ~TGuard() {
- Release();
- }
- inline void Release() noexcept {
- if (WasAcquired()) {
- TOps::Release(T_);
- T_ = nullptr;
- }
- }
- explicit inline operator bool() const noexcept {
- return WasAcquired();
- }
- inline bool WasAcquired() const noexcept {
- return T_ != nullptr;
- }
- inline T* GetMutex() const noexcept {
- return T_;
- }
- private:
- inline void Init(const T* t) noexcept {
- T_ = const_cast<T*>(t);
- TOps::Acquire(T_);
- }
- private:
- T* T_;
- };
- /*
- * {
- * auto guard = Guard(Lock_);
- * some code under guard
- * }
- */
- template <class T>
- static inline TGuard<T> Guard(const T& t) {
- return {&t};
- }
- /*
- * with_lock (Lock_) {
- * some code under guard
- * }
- */
- #define with_lock(X) \
- if (auto Y_GENERATE_UNIQUE_ID(__guard) = ::Guard(X); false) { \
- } else
- /*
- * auto guard = Guard(Lock_);
- * ... some code under lock
- * {
- * auto unguard = Unguard(guard);
- * ... some code not under lock
- * }
- * ... some code under lock
- */
- template <class T, class TOps = TCommonLockOps<T>>
- using TInverseGuard = TGuard<T, TInverseLockOps<TOps>>;
- template <class T, class TOps>
- static inline TInverseGuard<T, TOps> Unguard(const TGuard<T, TOps>& guard) {
- return {guard.GetMutex()};
- }
- template <class T>
- static inline TInverseGuard<T> Unguard(const T& mutex) {
- return {&mutex};
- }
- template <class T, class TOps = TTryLockOps<T>>
- class TTryGuard: public TNonCopyable {
- public:
- inline TTryGuard(const T& t) noexcept {
- Init(&t);
- }
- inline TTryGuard(const T* t) noexcept {
- Init(t);
- }
- inline TTryGuard(TTryGuard&& g) noexcept
- : T_(g.T_)
- {
- g.T_ = nullptr;
- }
- inline ~TTryGuard() {
- Release();
- }
- inline void Release() noexcept {
- if (WasAcquired()) {
- TOps::Release(T_);
- T_ = nullptr;
- }
- }
- inline bool WasAcquired() const noexcept {
- return T_ != nullptr;
- }
- explicit inline operator bool() const noexcept {
- return WasAcquired();
- }
- private:
- inline void Init(const T* t) noexcept {
- T_ = nullptr;
- T* tMutable = const_cast<T*>(t);
- if (TOps::TryAcquire(tMutable)) {
- T_ = tMutable;
- }
- }
- private:
- T* T_;
- };
|