[util] Add release() and reaquire() to scoped_lock

Added methods for releasing the lock held in a scoped_lock early, as
well as reacquiring it after. Useful when, eg a thread is about to block
and should not be holding the lock while blocked.
This commit is contained in:
Justin C. Miller
2022-01-23 19:40:00 -08:00
parent 0a07a7af01
commit 0394f29f70

View File

@@ -34,18 +34,37 @@ class scoped_lock
public: public:
inline scoped_lock( inline scoped_lock(
spinlock &lock, spinlock &lock,
const char *where = __builtin_FUNCTION() const char *where = __builtin_FUNCTION()) :
) : m_lock(lock), m_waiter {false, nullptr, where} { m_lock(lock),
m_waiter {false, nullptr, where},
m_is_locked {false}
{
m_lock.acquire(&m_waiter); m_lock.acquire(&m_waiter);
m_is_locked = true;
} }
inline ~scoped_lock() { inline ~scoped_lock() { release(); }
m_lock.release(&m_waiter);
/// Re-acquire the previously-held lock
inline void reacquire() {
if (!m_is_locked) {
m_lock.acquire(&m_waiter);
m_is_locked = true;
}
}
/// Release the held lock
inline void release() {
if (m_is_locked) {
m_lock.release(&m_waiter);
m_is_locked = false;
}
} }
private: private:
spinlock &m_lock; spinlock &m_lock;
spinlock::waiter m_waiter; spinlock::waiter m_waiter;
bool m_is_locked;
}; };
/// Scoped lock that owns a spinlock::waiter and calls /// Scoped lock that owns a spinlock::waiter and calls
@@ -57,18 +76,18 @@ public:
spinlock &lock, spinlock &lock,
const char *where = __builtin_FUNCTION() const char *where = __builtin_FUNCTION()
) : m_lock(lock), m_waiter {false, nullptr, where} { ) : m_lock(lock), m_waiter {false, nullptr, where} {
m_locked = m_lock.try_acquire(&m_waiter); m_is_locked = m_lock.try_acquire(&m_waiter);
} }
inline ~scoped_trylock() { inline ~scoped_trylock() {
if (m_locked) if (m_is_locked)
m_lock.release(&m_waiter); m_lock.release(&m_waiter);
} }
inline bool locked() const { return m_locked; } inline bool locked() const { return m_is_locked; }
private: private:
bool m_locked; bool m_is_locked;
spinlock &m_lock; spinlock &m_lock;
spinlock::waiter m_waiter; spinlock::waiter m_waiter;
}; };