diff --git a/Kernel/Locking/SpinLockProtectedValue.h b/Kernel/Locking/SpinLockProtectedValue.h new file mode 100644 index 0000000000..e4af19d8a3 --- /dev/null +++ b/Kernel/Locking/SpinLockProtectedValue.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Kernel { + +template +class SpinLockProtectedValue : private T + , public SpinLockContendedResource { + AK_MAKE_NONCOPYABLE(SpinLockProtectedValue); + AK_MAKE_NONMOVABLE(SpinLockProtectedValue); + +protected: + using LockedConst = SpinLockLockedResource; + using LockedMutable = SpinLockLockedResource; + + LockedConst lock_const() const { return LockedConst(static_cast(this), this->SpinLockContendedResource::m_spinlock); } + LockedMutable lock_mutable() { return LockedMutable(static_cast(this), this->SpinLockContendedResource::m_spinlock); } + +public: + using T::T; + + SpinLockProtectedValue() = default; + + template + decltype(auto) with(Callback callback) const + { + auto lock = lock_const(); + return callback(*lock); + } + + template + decltype(auto) with(Callback callback) + { + auto lock = lock_mutable(); + return callback(*lock); + } + + template + void for_each_const(Callback callback) const + { + with([&](const auto& value) { + for (auto& item : value) + callback(item); + }); + } + + template + void for_each(Callback callback) + { + with([&](auto& value) { + for (auto& item : value) + callback(item); + }); + } +}; + +} diff --git a/Kernel/Locking/SpinLockResource.h b/Kernel/Locking/SpinLockResource.h new file mode 100644 index 0000000000..f8d23b5da0 --- /dev/null +++ b/Kernel/Locking/SpinLockResource.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, the SerenityOS developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +template +class SpinLockLockedResource { + AK_MAKE_NONCOPYABLE(SpinLockLockedResource); + +public: + SpinLockLockedResource(T* value, RecursiveSpinLock& spinlock) + : m_value(value) + , m_scoped_spinlock(spinlock) + { + } + + ALWAYS_INLINE T const* operator->() const { return m_value; } + ALWAYS_INLINE T const& operator*() const { return *m_value; } + + ALWAYS_INLINE T* operator->() { return m_value; } + ALWAYS_INLINE T& operator*() { return *m_value; } + + ALWAYS_INLINE T const* get() const { return m_value; } + ALWAYS_INLINE T* get() { return m_value; } + +private: + T* m_value; + ScopedSpinLock m_scoped_spinlock; +}; + +class SpinLockContendedResource { + template + friend class SpinLockLockedResource; + + AK_MAKE_NONCOPYABLE(SpinLockContendedResource); + AK_MAKE_NONMOVABLE(SpinLockContendedResource); + +public: + SpinLockContendedResource() = default; + +protected: + mutable RecursiveSpinLock m_spinlock; +}; + +}