mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[util] Add try_aquire to spinlock
Also added a scoped_trylock class that mirrors scoped_lock, but uses try_aquire and has a scoped_lock::locked() accessor.
This commit is contained in:
@@ -17,8 +17,10 @@ public:
|
||||
{
|
||||
bool blocked;
|
||||
waiter *next;
|
||||
char const *where;
|
||||
};
|
||||
|
||||
bool try_acquire(waiter *w);
|
||||
void acquire(waiter *w);
|
||||
void release(waiter *w);
|
||||
|
||||
@@ -30,7 +32,10 @@ private:
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
inline scoped_lock(spinlock &lock) : m_lock(lock) {
|
||||
inline scoped_lock(
|
||||
spinlock &lock,
|
||||
const char *where = __builtin_FUNCTION()
|
||||
) : m_lock(lock), m_waiter {false, nullptr, where} {
|
||||
m_lock.acquire(&m_waiter);
|
||||
}
|
||||
|
||||
@@ -43,4 +48,29 @@ private:
|
||||
spinlock::waiter m_waiter;
|
||||
};
|
||||
|
||||
/// Scoped lock that owns a spinlock::waiter and calls
|
||||
/// spinlock::try_acquire
|
||||
class scoped_trylock
|
||||
{
|
||||
public:
|
||||
inline scoped_trylock(
|
||||
spinlock &lock,
|
||||
const char *where = __builtin_FUNCTION()
|
||||
) : m_lock(lock), m_waiter {false, nullptr, where} {
|
||||
m_locked = m_lock.try_acquire(&m_waiter);
|
||||
}
|
||||
|
||||
inline ~scoped_trylock() {
|
||||
if (m_locked)
|
||||
m_lock.release(&m_waiter);
|
||||
}
|
||||
|
||||
inline bool locked() const { return m_locked; }
|
||||
|
||||
private:
|
||||
bool m_locked;
|
||||
spinlock &m_lock;
|
||||
spinlock::waiter m_waiter;
|
||||
};
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -7,6 +7,17 @@ static constexpr int memorder = __ATOMIC_SEQ_CST;
|
||||
spinlock::spinlock() : m_lock {nullptr} {}
|
||||
spinlock::~spinlock() {}
|
||||
|
||||
bool
|
||||
spinlock::try_acquire(waiter *w)
|
||||
{
|
||||
w->next = nullptr;
|
||||
w->blocked = false;
|
||||
|
||||
// Point this lock at the waiter only if it's empty
|
||||
waiter *expected = nullptr;
|
||||
return __atomic_compare_exchange_n(&m_lock, &expected, w, false, memorder, memorder);
|
||||
}
|
||||
|
||||
void
|
||||
spinlock::acquire(waiter *w)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user