llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Raphael Isemann (Teemperor)

<details>
<summary>Changes</summary>

LLDB's code base has many variables that have an associated mutex that needs to 
be locked to safely access that variable from multiple threads. However, this 
locking scheme is currently not enforced by the compiler and code sometimes 
accesses these variables without aquiring the respective mutex first.

This patch introduces a `Guarded` class that strictly enforces that some memory 
is only accessed after the respective mutex has been aquired. This class hands 
out `Locked` objects for every access which guarentee that the mutex is held as 
long as the variable is in scope.

---
Full diff: https://github.com/llvm/llvm-project/pull/219421.diff


2 Files Affected:

- (modified) lldb/include/lldb/Utility/Locked.h (+28) 
- (modified) lldb/unittests/Utility/LockedTest.cpp (+37) 


``````````diff
diff --git a/lldb/include/lldb/Utility/Locked.h 
b/lldb/include/lldb/Utility/Locked.h
index acd34e454a918..f5d7b1aa8e4d9 100644
--- a/lldb/include/lldb/Utility/Locked.h
+++ b/lldb/include/lldb/Utility/Locked.h
@@ -168,6 +168,34 @@ template <typename T, typename Mutex = llvm::sys::RWMutex>
 using SharedLockedUP = SharedLocked<std::unique_ptr<const T>, Mutex>;
 /// @}
 
+/// Bundles a value of type `T` with the `Mutex` that guards it.
+///
+/// This class prevents accidential use of a value without aquiring the
+/// lock and should be preferred over a member + mutex pair.
+///
+/// `Mutex` must satisfy `Lockable` when calling `Lock()` and `SharedLockable`
+/// when calling `LockShared()`.
+template <typename T, typename Mutex = llvm::sys::RWMutex> class Guarded {
+public:
+  Guarded() = default;
+  explicit Guarded(T value) : m_value(std::move(value)) {}
+
+  Guarded(const Guarded &) = delete;
+  Guarded &operator=(const Guarded &) = delete;
+
+  /// Exclusive (read/write) access to the value.
+  Locked<T *, Mutex> Lock() { return Locked<T *, Mutex>(m_mutex, &m_value); }
+
+  /// Shared (read-only) access to the value.
+  SharedLocked<const T *, Mutex> LockShared() const {
+    return SharedLocked<const T *, Mutex>(m_mutex, &m_value);
+  }
+
+private:
+  mutable Mutex m_mutex;
+  T m_value{};
+};
+
 } // namespace lldb_private
 
 #endif // LLDB_UTILITY_LOCKED_H
diff --git a/lldb/unittests/Utility/LockedTest.cpp 
b/lldb/unittests/Utility/LockedTest.cpp
index cae24293dee2e..f898f21b56291 100644
--- a/lldb/unittests/Utility/LockedTest.cpp
+++ b/lldb/unittests/Utility/LockedTest.cpp
@@ -225,3 +225,40 @@ TEST(LockedTest, ExclusiveAccessOnRWMutex) {
   writer->value = 11;
   EXPECT_EQ(widget.value, 11);
 }
+
+// Guarded is neither copyable nor movable.
+static_assert(!std::is_copy_constructible_v<Guarded<Widget>>);
+static_assert(!std::is_move_constructible_v<Guarded<Widget>>);
+
+TEST(LockedTest, GuardedDefaultConstructed) {
+  Guarded<Widget> guarded;
+  EXPECT_EQ(guarded.Lock()->value, 0);
+}
+
+TEST(LockedTest, GuardedValueConstructed) {
+  Guarded<Widget> guarded(Widget{42});
+  EXPECT_EQ(guarded.Lock()->value, 42);
+}
+
+TEST(LockedTest, GuardedExclusiveAccessMutatesValue) {
+  Guarded<Widget> guarded;
+  guarded.Lock()->value = 7;
+  EXPECT_EQ(guarded.Lock()->value, 7);
+}
+
+TEST(LockedTest, GuardedSharedAccessIsReadOnly) {
+  Guarded<Widget> guarded(Widget{5});
+  SharedLocked<const Widget *, llvm::sys::RWMutex> reader =
+      guarded.LockShared();
+  EXPECT_EQ(reader->value, 5);
+  static_assert(std::is_same_v<decltype(reader.get()), const Widget *>,
+                "shared access borrows a const-qualified pointer");
+}
+
+// std::shared_mutex satisfies SharedLockable too, so Guarded works with it
+// as a drop-in replacement for llvm::sys::RWMutex.
+TEST(LockedTest, GuardedWorksWithStdSharedMutex) {
+  Guarded<Widget, std::shared_mutex> guarded;
+  guarded.Lock()->value = 3;
+  EXPECT_EQ(guarded.LockShared()->value, 3);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/219421
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to