#pragma once #include #include namespace chatterino { template class AccessGuard { public: AccessGuard(T &element, std::mutex &mutex) : element_(&element) , mutex_(&mutex) { this->mutex_->lock(); } AccessGuard(AccessGuard &&other) : element_(other.element_) , mutex_(other.mutex_) { other.isValid_ = false; } AccessGuard &operator=(AccessGuard &&other) { other.isValid_ = false; this->element_ = other.element_; this->mutex_ = other.element_; } ~AccessGuard() { if (this->isValid_) this->mutex_->unlock(); } T *operator->() const { return this->element_; } T &operator*() const { return *this->element_; } private: T *element_{}; std::mutex *mutex_{}; bool isValid_{true}; }; template class UniqueAccess { public: UniqueAccess() : element_(T()) { } UniqueAccess(const T &element) : element_(element) { } UniqueAccess(T &&element) : element_(element) { } UniqueAccess &operator=(const T &element) { this->element_ = element; return *this; } UniqueAccess &operator=(T &&element) { this->element_ = element; return *this; } AccessGuard access() const { return AccessGuard(this->element_, this->mutex_); } template ::value>> AccessGuard accessConst() const { return AccessGuard(this->element_, this->mutex_); } private: mutable T element_; mutable std::mutex mutex_; }; } // namespace chatterino