/* * Copyright (c) 2021, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include namespace Kernel { template class SpinlockProtected { AK_MAKE_NONCOPYABLE(SpinlockProtected); AK_MAKE_NONMOVABLE(SpinlockProtected); private: template class Locked { AK_MAKE_NONCOPYABLE(Locked); AK_MAKE_NONMOVABLE(Locked); public: Locked(U& value, RecursiveSpinlock& spinlock) : m_value(value) , m_locker(spinlock) { } ALWAYS_INLINE U const* operator->() const { return &m_value; } ALWAYS_INLINE U const& operator*() const { return m_value; } ALWAYS_INLINE U* operator->() { return &m_value; } ALWAYS_INLINE U& operator*() { return m_value; } ALWAYS_INLINE U const& get() const { return m_value; } ALWAYS_INLINE U& get() { return m_value; } private: U& m_value; SpinlockLocker m_locker; }; auto lock_const() const { return Locked(m_value, m_spinlock); } auto lock_mutable() { return Locked(m_value, m_spinlock); } public: SpinlockProtected() = 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); }); } private: T m_value; RecursiveSpinlock mutable m_spinlock; }; }