================ @@ -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
