1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:57: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 {
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 };
};