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;
|
bool blocked;
|
||||||
waiter *next;
|
waiter *next;
|
||||||
|
char const *where;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool try_acquire(waiter *w);
|
||||||
void acquire(waiter *w);
|
void acquire(waiter *w);
|
||||||
void release(waiter *w);
|
void release(waiter *w);
|
||||||
|
|
||||||
@@ -30,7 +32,10 @@ private:
|
|||||||
class scoped_lock
|
class scoped_lock
|
||||||
{
|
{
|
||||||
public:
|
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);
|
m_lock.acquire(&m_waiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,4 +48,29 @@ private:
|
|||||||
spinlock::waiter m_waiter;
|
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
|
} // namespace util
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ static constexpr int memorder = __ATOMIC_SEQ_CST;
|
|||||||
spinlock::spinlock() : m_lock {nullptr} {}
|
spinlock::spinlock() : m_lock {nullptr} {}
|
||||||
spinlock::~spinlock() {}
|
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
|
void
|
||||||
spinlock::acquire(waiter *w)
|
spinlock::acquire(waiter *w)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user