blob: efc091d5f8d422c490e45f222285f56af04e9b7c (
plain) (
tree)
|
|
#pragma once
#include <util/generic/noncopyable.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_;
};
|