Serenity Operating System
at master 93 lines 2.2 kB view raw
1/* 2 * Copyright (c) 2021, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <Kernel/Locking/Spinlock.h> 10 11namespace Kernel { 12 13template<typename T, LockRank Rank> 14class SpinlockProtected { 15 AK_MAKE_NONCOPYABLE(SpinlockProtected); 16 AK_MAKE_NONMOVABLE(SpinlockProtected); 17 18private: 19 template<typename U> 20 class Locked { 21 AK_MAKE_NONCOPYABLE(Locked); 22 AK_MAKE_NONMOVABLE(Locked); 23 24 public: 25 Locked(U& value, RecursiveSpinlock<Rank>& spinlock) 26 : m_value(value) 27 , m_locker(spinlock) 28 { 29 } 30 31 ALWAYS_INLINE U const* operator->() const { return &m_value; } 32 ALWAYS_INLINE U const& operator*() const { return m_value; } 33 34 ALWAYS_INLINE U* operator->() { return &m_value; } 35 ALWAYS_INLINE U& operator*() { return m_value; } 36 37 ALWAYS_INLINE U const& get() const { return m_value; } 38 ALWAYS_INLINE U& get() { return m_value; } 39 40 private: 41 U& m_value; 42 SpinlockLocker<RecursiveSpinlock<Rank>> m_locker; 43 }; 44 45 auto lock_const() const { return Locked<T const>(m_value, m_spinlock); } 46 auto lock_mutable() { return Locked<T>(m_value, m_spinlock); } 47 48public: 49 template<typename... Args> 50 SpinlockProtected(Args&&... args) 51 : m_value(forward<Args>(args)...) 52 { 53 } 54 55 template<typename Callback> 56 decltype(auto) with(Callback callback) const 57 { 58 auto lock = lock_const(); 59 return callback(*lock); 60 } 61 62 template<typename Callback> 63 decltype(auto) with(Callback callback) 64 { 65 auto lock = lock_mutable(); 66 return callback(*lock); 67 } 68 69 template<typename Callback> 70 void for_each_const(Callback callback) const 71 { 72 with([&](auto const& value) { 73 for (auto& item : value) 74 callback(item); 75 }); 76 } 77 78 template<typename Callback> 79 void for_each(Callback callback) 80 { 81 with([&](auto& value) { 82 for (auto& item : value) 83 callback(item); 84 }); 85 } 86 87private: 88 T m_value; 89 RecursiveSpinlock<Rank> mutable m_spinlock; 90 static constexpr LockRank const m_rank { Rank }; 91}; 92 93}