Serenity Operating System
at master 103 lines 2.7 kB view raw
1/* 2 * Copyright (c) 2021, the SerenityOS developers. 3 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <Kernel/Locking/Mutex.h> 11 12namespace Kernel { 13 14template<typename T> 15class MutexProtected { 16 AK_MAKE_NONCOPYABLE(MutexProtected); 17 AK_MAKE_NONMOVABLE(MutexProtected); 18 19private: 20 template<typename U, LockMode lock_mode> 21 class Locked { 22 AK_MAKE_NONCOPYABLE(Locked); 23 AK_MAKE_NONMOVABLE(Locked); 24 25 public: 26 Locked(U& value, Mutex& mutex, LockLocation const& location) 27 : m_value(value) 28 , m_locker(mutex, lock_mode, location) 29 { 30 } 31 32 ALWAYS_INLINE U const* operator->() const { return &m_value; } 33 ALWAYS_INLINE U const& operator*() const { return m_value; } 34 35 ALWAYS_INLINE U* operator->() 36 requires(!IsConst<U>) 37 { 38 return &m_value; 39 } 40 ALWAYS_INLINE U& operator*() 41 requires(!IsConst<U>) 42 { 43 return m_value; 44 } 45 46 ALWAYS_INLINE U const& get() const { return &m_value; } 47 ALWAYS_INLINE U& get() 48 requires(!IsConst<U>) 49 { 50 return &m_value; 51 } 52 53 private: 54 U& m_value; 55 MutexLocker m_locker; 56 }; 57 58 auto lock_shared(LockLocation const& location) const { return Locked<T const, LockMode::Shared>(m_value, m_mutex, location); } 59 auto lock_exclusive(LockLocation const& location) { return Locked<T, LockMode::Exclusive>(m_value, m_mutex, location); } 60 61public: 62 MutexProtected() = default; 63 64 template<typename Callback> 65 decltype(auto) with_shared(Callback callback, LockLocation const& location = LockLocation::current()) const 66 { 67 auto lock = lock_shared(location); 68 return callback(*lock); 69 } 70 71 template<typename Callback> 72 decltype(auto) with_exclusive(Callback callback, LockLocation const& location = LockLocation::current()) 73 { 74 auto lock = lock_exclusive(location); 75 return callback(*lock); 76 } 77 78 template<typename Callback> 79 void for_each_shared(Callback callback, LockLocation const& location = LockLocation::current()) const 80 { 81 with_shared([&](auto const& value) { 82 for (auto& item : value) 83 callback(item); 84 }, 85 location); 86 } 87 88 template<typename Callback> 89 void for_each_exclusive(Callback callback, LockLocation const& location = LockLocation::current()) 90 { 91 with_exclusive([&](auto& value) { 92 for (auto& item : value) 93 callback(item); 94 }, 95 location); 96 } 97 98private: 99 T m_value; 100 Mutex mutable m_mutex; 101}; 102 103}