================
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TARGET_TARGETAPILOCK_H
+#define LLDB_TARGET_TARGETAPILOCK_H
+
+#include "lldb/lldb-forward.h"
+#include <mutex>
+
+namespace lldb_private {
+
+/// A Lockable handle over a Target's API mutex, returned by
+/// Target::GetAPIMutex() and backing the public lldb::SBMutex.
+///
+/// A handle may be constructed on one thread and then locked/unlocked
+/// on a different one, so lock()/try_lock() (re-)resolve which real
+/// mutex to use fresh on every call, rather than caching a single
+/// resolution for the handle's lifetime. The matching unlock() replays
+/// the exact resolution that call produced, rather than re-resolving,
+/// so the calling thread's policy at unlock() time can't cause it to
+/// release the wrong mutex (or fail to release the one it actually
+/// holds).
+///
+/// Default-constructed (or moved-from) handles are a genuine no-op: no
+/// synchronization primitive is touched at all. Move-only; the
+/// destructor releases the lock if one is currently held.
+class TargetAPILock {
+public:
+  TargetAPILock() = default;
+  explicit TargetAPILock(lldb::TargetSP target_sp)
+      : m_target_sp(std::move(target_sp)) {}
+
+  TargetAPILock(TargetAPILock &&other) noexcept { *this = std::move(other); }
+  TargetAPILock &operator=(TargetAPILock &&other) noexcept {
+    if (this != &other) {
+      unlock();
+      m_mutex = other.m_mutex;
+      m_locked = other.m_locked;
+      m_target_sp = std::move(other.m_target_sp);
+      other.m_mutex = nullptr;
+      other.m_locked = false;
+    }
+    return *this;
+  }
+
+  TargetAPILock(const TargetAPILock &) = delete;
+  TargetAPILock &operator=(const TargetAPILock &) = delete;
+
+  ~TargetAPILock() { unlock(); }
+
+  void lock();
+  bool try_lock();
+
+  void unlock() {
+    if (m_locked) {
+      if (m_mutex)
+        m_mutex->unlock();
+      m_locked = false;
+      // Drop the resolution: the next lock()/try_lock() must resolve
+      // fresh rather than reuse it.
+      m_mutex = nullptr;
+    }
+  }
+
+  bool owns_lock() const { return m_locked; }
----------------
JDevlieghere wrote:

Can you explain the need for this?

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

Reply via email to