Kernel: Simplify MutexProtected<T>

This patch removes the MutexContendedResource<T> helper class,
and MutexProtected<T> no longer inherits from T.
Instead, MutexProtected<T> simply has a T and a Mutex.

The LockedResource<T, LockMode> helper class is made a private nested
class in MutexProtected.
This commit is contained in:
Andreas Kling 2021-08-22 00:20:03 +02:00
parent c2fc33becd
commit 532ffa7ddb
2 changed files with 35 additions and 65 deletions

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/StdLibExtras.h>
#include <Kernel/Locking/Mutex.h>
namespace Kernel {
template<typename T, LockMode LockingMode>
class LockedResource {
AK_MAKE_NONCOPYABLE(LockedResource);
public:
LockedResource(T* value, Mutex& mutex, LockLocation const& location)
: m_value(value)
, m_mutex_locker(mutex, LockingMode, location)
{
}
ALWAYS_INLINE T const* operator->() const { return m_value; }
ALWAYS_INLINE T const& operator*() const { return *m_value; }
ALWAYS_INLINE T* operator->() requires(!IsConst<T>) { return m_value; }
ALWAYS_INLINE T& operator*() requires(!IsConst<T>) { return *m_value; }
ALWAYS_INLINE T const* get() const { return m_value; }
ALWAYS_INLINE T* get() requires(!IsConst<T>) { return m_value; }
private:
T* m_value;
MutexLocker m_mutex_locker;
};
class MutexContendedResource {
template<typename, LockMode>
friend class LockedResource;
AK_MAKE_NONCOPYABLE(MutexContendedResource);
AK_MAKE_NONMOVABLE(MutexContendedResource);
public:
MutexContendedResource() = default;
protected:
mutable Mutex m_mutex;
};
}

View file

@ -1,33 +1,52 @@
/*
* Copyright (c) 2021, the SerenityOS developers.
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <Kernel/Locking/LockLocation.h>
#include <Kernel/Locking/MutexContendedResource.h>
#include <Kernel/Locking/Mutex.h>
namespace Kernel {
template<typename T>
class MutexProtected
: private T
, public MutexContendedResource {
class MutexProtected {
AK_MAKE_NONCOPYABLE(MutexProtected);
AK_MAKE_NONMOVABLE(MutexProtected);
protected:
using LockedShared = LockedResource<T const, LockMode::Shared>;
using LockedExclusive = LockedResource<T, LockMode::Exclusive>;
private:
template<typename U, LockMode lock_mode>
class Locked {
AK_MAKE_NONCOPYABLE(Locked);
AK_MAKE_NONMOVABLE(Locked);
LockedShared lock_shared(LockLocation const& location) const { return LockedShared(this, this->MutexContendedResource::m_mutex, location); }
LockedExclusive lock_exclusive(LockLocation const& location) { return LockedExclusive(this, this->MutexContendedResource::m_mutex, location); }
public:
Locked(U& value, Mutex& mutex, LockLocation const& location)
: m_value(value)
, m_locker(mutex, lock_mode, location)
{
}
ALWAYS_INLINE U const* operator->() const { return &m_value; }
ALWAYS_INLINE U const& operator*() const { return m_value; }
ALWAYS_INLINE U* operator->() requires(!IsConst<U>) { return &m_value; }
ALWAYS_INLINE U& operator*() requires(!IsConst<U>) { return m_value; }
ALWAYS_INLINE U const& get() const { return &m_value; }
ALWAYS_INLINE U& get() requires(!IsConst<U>) { return &m_value; }
private:
U& m_value;
MutexLocker m_locker;
};
auto lock_shared(LockLocation const& location) const { return Locked<T const, LockMode::Shared>(m_value, m_mutex, location); }
auto lock_exclusive(LockLocation const& location) { return Locked<T, LockMode::Exclusive>(m_value, m_mutex, location); }
public:
using T::T;
MutexProtected() = default;
template<typename Callback>
@ -63,6 +82,10 @@ public:
},
location);
}
private:
T m_value;
Mutex mutable m_mutex;
};
}