From: Remi Gacogne Date: Fri, 30 Apr 2021 13:42:10 +0000 (+0200) Subject: Add SharedLockGuarded, a read-write lock version of LockGuarded X-Git-Tag: dnsdist-1.7.0-alpha1~62^2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e82ff2a18e487b4d6813105c50ec3437044c1c43;p=thirdparty%2Fpdns.git Add SharedLockGuarded, a read-write lock version of LockGuarded --- diff --git a/pdns/lock.hh b/pdns/lock.hh index ed4b07a6c3..d3c4245415 100644 --- a/pdns/lock.hh +++ b/pdns/lock.hh @@ -213,6 +213,10 @@ public: { } + explicit LockGuarded() + { + } + LockGuardedTryHolder try_lock() { return LockGuardedTryHolder(d_value, d_mutex); @@ -227,3 +231,152 @@ private: std::mutex d_mutex; T d_value; }; + +template +class SharedLockGuardedHolder +{ +public: + explicit SharedLockGuardedHolder(T& value, std::shared_mutex& mutex): d_lock(mutex), d_value(value) + { + } + + T& operator*() const noexcept { + return d_value; + } + + T* operator->() const noexcept { + return &d_value; + } + +private: + std::lock_guard d_lock; + T& d_value; +}; + +template +class SharedLockGuardedTryHolder +{ +public: + explicit SharedLockGuardedTryHolder(T& value, std::shared_mutex& mutex): d_lock(mutex, std::try_to_lock), d_value(value) + { + } + + T& operator*() const { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return d_value; + } + + T* operator->() const { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return &d_value; + } + + operator bool() const noexcept { + return d_lock.owns_lock(); + } + + bool owns_lock() const noexcept { + return d_lock.owns_lock(); + } + +private: + std::unique_lock d_lock; + T& d_value; +}; + +template +class SharedLockGuardedNonExclusiveHolder +{ +public: + explicit SharedLockGuardedNonExclusiveHolder(const T& value, std::shared_mutex& mutex): d_lock(mutex), d_value(value) + { + } + + const T& operator*() const noexcept { + return d_value; + } + + const T* operator->() const noexcept { + return &d_value; + } + +private: + std::shared_lock d_lock; + const T& d_value; +}; + +template +class SharedLockGuardedNonExclusiveTryHolder +{ +public: + explicit SharedLockGuardedNonExclusiveTryHolder(const T& value, std::shared_mutex& mutex): d_lock(mutex, std::try_to_lock), d_value(value) + { + } + + const T& operator*() const { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return d_value; + } + + const T* operator->() const { + if (!owns_lock()) { + throw std::runtime_error("Trying to access data protected by a mutex while the lock has not been acquired"); + } + return &d_value; + } + + operator bool() const noexcept { + return d_lock.owns_lock(); + } + + bool owns_lock() const noexcept { + return d_lock.owns_lock(); + } + +private: + std::shared_lock d_lock; + const T& d_value; +}; + +template +class SharedLockGuarded +{ +public: + explicit SharedLockGuarded(T value): d_value(std::move(value)) + { + } + + explicit SharedLockGuarded() + { + } + + SharedLockGuardedTryHolder try_lock() + { + return SharedLockGuardedTryHolder(d_value, d_mutex); + } + + SharedLockGuardedHolder lock() + { + return SharedLockGuardedHolder(d_value, d_mutex); + } + + SharedLockGuardedNonExclusiveTryHolder try_read_lock() + { + return SharedLockGuardedNonExclusiveTryHolder(d_value, d_mutex); + } + + SharedLockGuardedNonExclusiveHolder read_lock() + { + return SharedLockGuardedNonExclusiveHolder(d_value, d_mutex); + } + +private: + std::shared_mutex d_mutex; + T d_value; +};