Make AccessGuard use a shared_mutex instead (#2702)

This allows `accessConst` to use a shared lock instead of a unique lock
This commit is contained in:
pajlada
2021-05-01 17:19:41 +02:00
committed by GitHub
parent c413a0984e
commit 115d198434
9 changed files with 109 additions and 33 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ ChannelChatters::ChannelChatters(Channel &channel)
{
}
AccessGuard<const UsernameSet> ChannelChatters::accessChatters() const
SharedAccessGuard<const UsernameSet> ChannelChatters::accessChatters() const
{
return this->chatters_.accessConst();
}
+1 -1
View File
@@ -15,7 +15,7 @@ public:
ChannelChatters(Channel &channel);
virtual ~ChannelChatters() = default; // add vtable
AccessGuard<const UsernameSet> accessChatters() const;
SharedAccessGuard<const UsernameSet> accessChatters() const;
void addRecentChatter(const QString &user);
void addJoinedUser(const QString &user);
+17 -20
View File
@@ -1,39 +1,33 @@
#pragma once
#include <mutex>
#include <shared_mutex>
#include <type_traits>
namespace chatterino {
template <typename T>
template <typename T, typename LockType = std::unique_lock<std::shared_mutex>>
class AccessGuard
{
public:
AccessGuard(T &element, std::mutex &mutex)
AccessGuard(T &element, std::shared_mutex &mutex)
: element_(&element)
, mutex_(&mutex)
, lock_(mutex)
{
this->mutex_->lock();
}
AccessGuard(AccessGuard<T> &&other)
AccessGuard(AccessGuard<T, LockType> &&other)
: element_(other.element_)
, mutex_(other.mutex_)
, lock_(std::move(other.lock_))
{
other.isValid_ = false;
}
AccessGuard<T> &operator=(AccessGuard<T> &&other)
AccessGuard<T, LockType> &operator=(AccessGuard<T, LockType> &&other)
{
other.isValid_ = false;
this->element_ = other.element_;
this->mutex_ = other.element_;
}
this->lock_ = std::move(other.lock_);
~AccessGuard()
{
if (this->isValid_)
this->mutex_->unlock();
return *this;
}
T *operator->() const
@@ -48,10 +42,13 @@ public:
private:
T *element_{};
std::mutex *mutex_{};
bool isValid_{true};
LockType lock_;
};
template <typename T>
using SharedAccessGuard =
AccessGuard<const T, std::shared_lock<std::shared_mutex>>;
template <typename T>
class UniqueAccess
{
@@ -90,14 +87,14 @@ public:
template <typename X = T,
typename = std::enable_if_t<!std::is_const<X>::value>>
AccessGuard<const X> accessConst() const
SharedAccessGuard<const X> accessConst() const
{
return AccessGuard<const T>(this->element_, this->mutex_);
return SharedAccessGuard<const T>(this->element_, this->mutex_);
}
private:
mutable T element_;
mutable std::mutex mutex_;
mutable std::shared_mutex mutex_;
};
} // namespace chatterino