MutexProtected.h 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. #pragma once
  8. #include <Kernel/Locking/Mutex.h>
  9. namespace Kernel {
  10. template<typename T>
  11. class MutexProtected {
  12. AK_MAKE_NONCOPYABLE(MutexProtected);
  13. AK_MAKE_NONMOVABLE(MutexProtected);
  14. private:
  15. template<typename U, LockMode lock_mode>
  16. class Locked {
  17. AK_MAKE_NONCOPYABLE(Locked);
  18. AK_MAKE_NONMOVABLE(Locked);
  19. public:
  20. Locked(U& value, Mutex& mutex, LockLocation const& location)
  21. : m_value(value)
  22. , m_locker(mutex, lock_mode, location)
  23. {
  24. }
  25. ALWAYS_INLINE U const* operator->() const { return &m_value; }
  26. ALWAYS_INLINE U const& operator*() const { return m_value; }
  27. ALWAYS_INLINE U* operator->() requires(!IsConst<U>) { return &m_value; }
  28. ALWAYS_INLINE U& operator*() requires(!IsConst<U>) { return m_value; }
  29. ALWAYS_INLINE U const& get() const { return &m_value; }
  30. ALWAYS_INLINE U& get() requires(!IsConst<U>) { return &m_value; }
  31. private:
  32. U& m_value;
  33. MutexLocker m_locker;
  34. };
  35. auto lock_shared(LockLocation const& location) const { return Locked<T const, LockMode::Shared>(m_value, m_mutex, location); }
  36. auto lock_exclusive(LockLocation const& location) { return Locked<T, LockMode::Exclusive>(m_value, m_mutex, location); }
  37. public:
  38. MutexProtected() = default;
  39. template<typename Callback>
  40. decltype(auto) with_shared(Callback callback, LockLocation const& location = LockLocation::current()) const
  41. {
  42. auto lock = lock_shared(location);
  43. return callback(*lock);
  44. }
  45. template<typename Callback>
  46. decltype(auto) with_exclusive(Callback callback, LockLocation const& location = LockLocation::current())
  47. {
  48. auto lock = lock_exclusive(location);
  49. return callback(*lock);
  50. }
  51. template<typename Callback>
  52. void for_each_shared(Callback callback, LockLocation const& location = LockLocation::current()) const
  53. {
  54. with_shared([&](const auto& value) {
  55. for (auto& item : value)
  56. callback(item);
  57. },
  58. location);
  59. }
  60. template<typename Callback>
  61. void for_each_exclusive(Callback callback, LockLocation const& location = LockLocation::current())
  62. {
  63. with_exclusive([&](auto& value) {
  64. for (auto& item : value)
  65. callback(item);
  66. },
  67. location);
  68. }
  69. private:
  70. T m_value;
  71. Mutex mutable m_mutex;
  72. };
  73. }