1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:37:45 +00:00

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.
This commit is contained in:
Brian Gianforcaro 2021-07-19 10:32:55 -07:00 committed by Gunnar Beutner
parent 354e18a5a0
commit bb1fa019de

View file

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