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:
@@ -11,7 +11,7 @@ ChannelChatters::ChannelChatters(Channel &channel)
|
||||
{
|
||||
}
|
||||
|
||||
AccessGuard<const UsernameSet> ChannelChatters::accessChatters() const
|
||||
SharedAccessGuard<const UsernameSet> ChannelChatters::accessChatters() const
|
||||
{
|
||||
return this->chatters_.accessConst();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user