From 0394f29f704a7471e023b074c9aff10123e2e6c9 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sun, 23 Jan 2022 19:40:00 -0800 Subject: [PATCH] [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. --- src/libraries/util/include/util/spinlock.h | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/libraries/util/include/util/spinlock.h b/src/libraries/util/include/util/spinlock.h index f22b19d..aabb963 100644 --- a/src/libraries/util/include/util/spinlock.h +++ b/src/libraries/util/include/util/spinlock.h @@ -34,18 +34,37 @@ class scoped_lock public: inline scoped_lock( spinlock &lock, - const char *where = __builtin_FUNCTION() - ) : m_lock(lock), m_waiter {false, nullptr, where} { + const char *where = __builtin_FUNCTION()) : + m_lock(lock), + m_waiter {false, nullptr, where}, + m_is_locked {false} + { m_lock.acquire(&m_waiter); + m_is_locked = true; } - inline ~scoped_lock() { - m_lock.release(&m_waiter); + inline ~scoped_lock() { release(); } + + /// 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: spinlock &m_lock; spinlock::waiter m_waiter; + bool m_is_locked; }; /// Scoped lock that owns a spinlock::waiter and calls @@ -57,18 +76,18 @@ public: spinlock &lock, const char *where = __builtin_FUNCTION() ) : 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() { - if (m_locked) + if (m_is_locked) m_lock.release(&m_waiter); } - inline bool locked() const { return m_locked; } + inline bool locked() const { return m_is_locked; } private: - bool m_locked; + bool m_is_locked; spinlock &m_lock; spinlock::waiter m_waiter; };