diff --git a/clang/docs/ThreadSafetyAnalysis.rst b/clang/docs/ThreadSafetyAnalysis.rst --- a/clang/docs/ThreadSafetyAnalysis.rst +++ b/clang/docs/ThreadSafetyAnalysis.rst @@ -402,6 +402,9 @@ and destructor refer to the capability via different names; see the ``MutexLocker`` class in :ref:`mutexheader`, below. +Scoped capabilities are associated with a set of (proper) capabilities on +construction, every subsequent operation is forwarded to that set. + TRY_ACQUIRE(, ...), TRY_ACQUIRE_SHARED(, ...) --------------------------------------------------------- @@ -886,6 +889,9 @@ const Mutex& operator!() const { return *this; } }; + struct adopt_lock_t {} inline constexpr adopt_lock = {}; + struct defer_lock_t {} inline constexpr defer_lock = {}; + struct shared_lock_t {} inline constexpr shared_lock = {}; // MutexLocker is an RAII class that acquires a mutex in its constructor, and // releases it in its destructor. @@ -894,12 +900,49 @@ Mutex* mut; public: + // Acquires mu, implicitly acquires *this and connects it to mu. MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu) { mu->Lock(); } + // Assumes mu is held, implicitly acquires *this and connects it to mu. + MutexLocker(t_mutex &mu, adopt_lock_t) REQUIRES(mu) : mut(mu) {} + + // Acquires mu in shared mode, implicitly acquires *this and connects to mu. + MutexLocker(Mutex *mu, shared_lock_t) ACQUIRE_SHARED(mu) : mut(mu) { + mu->ReaderLock(); + } + // Assumes mu is held in shared mode, implicitly acquires *this and + // connects it to mu. + MutexLocker(t_mutex &mu, adopt_lock_t, shared_lock_t) REQUIRES_SHARED(mu) : mut(mu) {} + + // Assumes mu is not held, implicitly acquires *this and connects it to mu. + MutexLocker(t_mutex &mu, defer_lock_t) EXCLUDES(mu) : mut(mu) {} + + // Releases *this and all underlying capabilities, if they are still held. + // There is no warning on double unlock. ~MutexLocker() RELEASE() { + mut->GenericUnlock(); + } + + // (Re-)Acquire all underlying capabilities exclusively. + void Lock() ACQUIRE() { + mut->Lock(); + } + + // (Re-)Acquire all underlying capabilities in shared mode. + void ReaderLock() ACQUIRE_SHARED() { + mut->ReaderLock(); + } + + // Releases *this and all underlying capabilities. Warns on double unlock. + void Unlock() RELEASE() { mut->Unlock(); } + + // Releases *this and all underlying capabilities. Warns on double unlock. + void ReaderUnlock() RELEASE() { + mut->ReaderUnlock(); + } };