1 #pragma once 2 3 #include <mutex> 4 #include <shared_mutex> 5 #include <type_traits> 6 7 namespace chatterino { 8 9 template <typename T, typename LockType = std::unique_lock<std::shared_mutex>> 10 class AccessGuard 11 { 12 public: AccessGuard(T & element,std::shared_mutex & mutex)13 AccessGuard(T &element, std::shared_mutex &mutex) 14 : element_(&element) 15 , lock_(mutex) 16 { 17 } 18 AccessGuard(AccessGuard<T,LockType> && other)19 AccessGuard(AccessGuard<T, LockType> &&other) 20 : element_(other.element_) 21 , lock_(std::move(other.lock_)) 22 { 23 } 24 operator =(AccessGuard<T,LockType> && other)25 AccessGuard<T, LockType> &operator=(AccessGuard<T, LockType> &&other) 26 { 27 this->element_ = other.element_; 28 this->lock_ = std::move(other.lock_); 29 30 return *this; 31 } 32 operator ->() const33 T *operator->() const 34 { 35 return this->element_; 36 } 37 operator *() const38 T &operator*() const 39 { 40 return *this->element_; 41 } 42 43 private: 44 T *element_{}; 45 LockType lock_; 46 }; 47 48 template <typename T> 49 using SharedAccessGuard = 50 AccessGuard<const T, std::shared_lock<std::shared_mutex>>; 51 52 template <typename T> 53 class UniqueAccess 54 { 55 public: UniqueAccess()56 UniqueAccess() 57 : element_(T()) 58 { 59 } 60 UniqueAccess(const T & element)61 UniqueAccess(const T &element) 62 : element_(element) 63 { 64 } 65 UniqueAccess(T && element)66 UniqueAccess(T &&element) 67 : element_(std::move(element)) 68 { 69 } 70 operator =(const T & element)71 UniqueAccess<T> &operator=(const T &element) 72 { 73 this->element_ = element; 74 return *this; 75 } 76 operator =(T && element)77 UniqueAccess<T> &operator=(T &&element) 78 { 79 this->element_ = std::move(element); 80 return *this; 81 } 82 access() const83 AccessGuard<T> access() const 84 { 85 return AccessGuard<T>(this->element_, this->mutex_); 86 } 87 88 template <typename X = T, 89 typename = std::enable_if_t<!std::is_const<X>::value>> accessConst() const90 SharedAccessGuard<const X> accessConst() const 91 { 92 return SharedAccessGuard<const T>(this->element_, this->mutex_); 93 } 94 95 private: 96 mutable T element_; 97 mutable std::shared_mutex mutex_; 98 }; 99 100 } // namespace chatterino 101