[PATCH] D87066: Thread safety analysis: Improve documentation for scoped capabilities

Aaron Puchert via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 3 15:43:58 PDT 2020


aaronpuchert updated this revision to Diff 289826.
aaronpuchert marked an inline comment as done.
aaronpuchert added a comment.

- More detailed description how scoped capabilities work.
- Make the comment wording more consistent with existing comments and the previous explanation.
- Properly implement the destructor in the presence of an `Unlock()` function: we need to keep track of the status then.
- Add try-acquire functions on scoped lock.
- Fix compiler errors.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87066/new/

https://reviews.llvm.org/D87066

Files:
  clang/docs/ThreadSafetyAnalysis.rst


Index: clang/docs/ThreadSafetyAnalysis.rst
===================================================================
--- clang/docs/ThreadSafetyAnalysis.rst
+++ clang/docs/ThreadSafetyAnalysis.rst
@@ -402,6 +402,13 @@
 and destructor refer to the capability via different names; see the
 ``MutexLocker`` class in :ref:`mutexheader`, below.
 
+Scoped capabilities are treated as capabilities that are implicitly acquired
+on construction and released on destruction. They are associated with
+the set of (regular) capabilities named in thread safety attributes on the
+constructor. Acquire-type attributes on other member functions are treated as
+applying to that set of associated capabilities, while ``RELEASE`` implies that
+a function releases all associated capabilities in whatever mode they're held.
+
 
 TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...)
 ---------------------------------------------------------
@@ -886,19 +893,78 @@
     const Mutex& operator!() const { return *this; }
   };
 
+  // Tag types for selecting a constructor.
+  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.
   class SCOPED_CAPABILITY MutexLocker {
   private:
     Mutex* mut;
+    bool locked;
 
   public:
-    MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu) {
+    // Acquire mu, implicitly acquire *this and associate it with mu.
+    MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu), locked(true) {
       mu->Lock();
     }
+
+    // Assume mu is held, implicitly acquire *this and associate it with mu.
+    MutexLocker(Mutex *mu, adopt_lock_t) REQUIRES(mu) : mut(mu), locked(true) {}
+
+    // Acquire mu in shared mode, implicitly acquire *this and connect to mu.
+    MutexLocker(Mutex *mu, shared_lock_t) ACQUIRE_SHARED(mu) : mut(mu), locked(true) {
+      mu->ReaderLock();
+    }
+
+    // Assume mu is held in shared mode, implicitly acquire *this and associate it with mu.
+    MutexLocker(Mutex *mu, adopt_lock_t, shared_lock_t) REQUIRES_SHARED(mu)
+      : mut(mu), locked(true) {}
+
+    // Assume mu is not held, implicitly acquire *this and associate it with mu.
+    MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {}
+
+    // Release *this and all associated mutexes, if they are still held.
+    // There is no warning if the scope was already unlocked before.
     ~MutexLocker() RELEASE() {
+      if (locked)
+        mut->GenericUnlock();
+    }
+
+    // Acquire all associated mutexes exclusively.
+    void Lock() ACQUIRE() {
+      mut->Lock();
+      locked = true;
+    }
+
+    // Try to acquire all associated mutexes exclusively.
+    bool TryLock() TRY_ACQUIRE(true) {
+      return locked = mut->TryLock();
+    }
+
+    // Acquire all associated mutexes in shared mode.
+    void ReaderLock() ACQUIRE_SHARED() {
+      mut->ReaderLock();
+      locked = true;
+    }
+
+    // Try to acquire all associated mutexes in shared mode.
+    bool ReaderTryLock() TRY_ACQUIRE_SHARED(true) {
+      return locked = mut->ReaderTryLock();
+    }
+
+    // Release all associated mutexes. Warn on double unlock.
+    void Unlock() RELEASE() {
       mut->Unlock();
+      locked = false;
+    }
+
+    // Release all associated mutexes. Warn on double unlock.
+    void ReaderUnlock() RELEASE() {
+      mut->ReaderUnlock();
+      locked = false;
     }
   };
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87066.289826.patch
Type: text/x-patch
Size: 3559 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200903/047924f7/attachment.bin>


More information about the cfe-commits mailing list