소스 검색

Kernel: Allow MutexLocker to be conditionally initialized

There are cases where we want to conditionally take a lock, but still
would like to use an RAII type to make sure we don't leak the lock.

This was previously impossible to do with `MutexLocker` due to it's
design. This commit tweaks the design to allow the object to be
initialized to an "empty" state without a lock associated, so it does
nothing, and then later a lock can be "attached" to the locker.

I realized that the get_lock() API's where also unused, and would no
longer make sense for empty locks, so they were removed.
Brian Gianforcaro 4 년 전
부모
커밋
bb1fa019de
1개의 변경된 파일35개의 추가작업 그리고 10개의 파일을 삭제
  1. 35 10
      Kernel/Mutex.h

+ 35 - 10
Kernel/Mutex.h

@@ -106,18 +106,26 @@ private:
 };
 
 class MutexLocker {
+    AK_MAKE_NONCOPYABLE(MutexLocker);
+
 public:
+    ALWAYS_INLINE explicit MutexLocker()
+        : m_lock(nullptr)
+        , m_locked(false)
+    {
+    }
+
 #if LOCK_DEBUG
     ALWAYS_INLINE explicit MutexLocker(Mutex& l, Mutex::Mode mode = Mutex::Mode::Exclusive, const SourceLocation& location = SourceLocation::current())
 #else
     ALWAYS_INLINE explicit MutexLocker(Mutex& l, Mutex::Mode mode = Mutex::Mode::Exclusive)
 #endif
-        : m_lock(l)
+        : m_lock(&l)
     {
 #if LOCK_DEBUG
-        m_lock.lock(mode, location);
+        m_lock->lock(mode, location);
 #else
-        m_lock.lock(mode);
+        m_lock->lock(mode);
 #endif
     }
 
@@ -126,11 +134,30 @@ public:
         if (m_locked)
             unlock();
     }
+
     ALWAYS_INLINE void unlock()
     {
+        VERIFY(m_lock);
         VERIFY(m_locked);
         m_locked = false;
-        m_lock.unlock();
+        m_lock->unlock();
+    }
+
+#if LOCK_DEBUG
+    ALWAYS_INLINE void attach_and_lock(Mutex& lock, Mutex::Mode mode = Mutex::Mode::Exclusive, const SourceLocation& location = SourceLocation::current())
+#else
+    ALWAYS_INLINE void attach_and_lock(Mutex& lock, Mutex::Mode mode = Mutex::Mode::Exclusive)
+#endif
+    {
+        VERIFY(!m_locked);
+        m_lock = &lock;
+        m_locked = true;
+
+#if LOCK_DEBUG
+        m_lock->lock(mode, location);
+#else
+        m_lock->lock(mode);
+#endif
     }
 
 #if LOCK_DEBUG
@@ -139,21 +166,19 @@ public:
     ALWAYS_INLINE void lock(Mutex::Mode mode = Mutex::Mode::Exclusive)
 #endif
     {
+        VERIFY(m_lock);
         VERIFY(!m_locked);
         m_locked = true;
 
 #if LOCK_DEBUG
-        m_lock.lock(mode, location);
+        m_lock->lock(mode, location);
 #else
-        m_lock.lock(mode);
+        m_lock->lock(mode);
 #endif
     }
 
-    Mutex& get_lock() { return m_lock; }
-    const Mutex& get_lock() const { return m_lock; }
-
 private:
-    Mutex& m_lock;
+    Mutex* m_lock;
     bool m_locked { true };
 };