std::unique_lock<std::shared_mutex> d_lock;
};
+
+template <typename T>
+class LockGuardedHolder
+{
+public:
+ explicit LockGuardedHolder(T& value, std::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<std::mutex> d_lock;
+ T& d_value;
+};
+
+template <typename T>
+class LockGuardedTryHolder
+{
+public:
+ explicit LockGuardedTryHolder(T& value, std::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<std::mutex> d_lock;
+ T& d_value;
+};
+
+template <typename T>
+class LockGuarded
+{
+public:
+ explicit LockGuarded(T value): d_value(std::move(value))
+ {
+ }
+
+ LockGuardedTryHolder<T> try_lock()
+ {
+ return LockGuardedTryHolder<T>(d_value, d_mutex);
+ }
+
+ LockGuardedHolder<T> lock()
+ {
+ return LockGuardedHolder<T>(d_value, d_mutex);
+ }
+
+private:
+ std::mutex d_mutex;
+ T d_value;
+};