Implement try_lock

This commit is contained in:
John Sully 2019-02-22 01:23:31 -05:00
parent ebf0ae3e97
commit d016b967c5
5 changed files with 52 additions and 8 deletions

View File

@ -774,6 +774,11 @@ void aeAcquireLock()
g_lock.lock();
}
int aeTryAcquireLock()
{
return g_lock.try_lock();
}
void aeReleaseLock()
{
g_lock.unlock();

View File

@ -159,6 +159,7 @@ int aeGetSetSize(aeEventLoop *eventLoop);
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);
void aeAcquireLock();
int aeTryAcquireLock();
void aeReleaseLock();
int aeThreadOwnsLock();

View File

@ -53,8 +53,8 @@ static pid_t gettid()
extern "C" void fastlock_init(struct fastlock *lock)
{
lock->m_active = 0;
lock->m_avail = 0;
lock->m_ticket.m_active = 0;
lock->m_ticket.m_avail = 0;
lock->m_depth = 0;
}
@ -66,12 +66,12 @@ extern "C" void fastlock_lock(struct fastlock *lock)
return;
}
unsigned myticket = __atomic_fetch_add(&lock->m_avail, 1, __ATOMIC_ACQ_REL);
unsigned myticket = __atomic_fetch_add(&lock->m_ticket.m_avail, 1, __ATOMIC_ACQ_REL);
if (__atomic_load_4(&lock->m_active, __ATOMIC_ACQUIRE) != myticket)
if (__atomic_load_2(&lock->m_ticket.m_active, __ATOMIC_ACQUIRE) != myticket)
{
int cloops = 1;
while (__atomic_load_4(&lock->m_active, __ATOMIC_ACQUIRE) != myticket)
while (__atomic_load_2(&lock->m_ticket.m_active, __ATOMIC_ACQUIRE) != myticket)
{
if ((++cloops % 1024*1024) == 0)
sched_yield();
@ -83,6 +83,33 @@ extern "C" void fastlock_lock(struct fastlock *lock)
__sync_synchronize();
}
extern "C" int fastlock_trylock(struct fastlock *lock)
{
if ((int)__atomic_load_4(&lock->m_pidOwner, __ATOMIC_ACQUIRE) == gettid())
{
++lock->m_depth;
return true;
}
// cheap test
if (lock->m_ticket.m_active != lock->m_ticket.m_avail)
return false;
uint16_t active = __atomic_load_2(&lock->m_ticket.m_active, __ATOMIC_ACQUIRE);
uint16_t next = active + 1;
struct ticket ticket_expect { active, active };
struct ticket ticket_setiflocked { active, next };
if (__atomic_compare_exchange(&lock->m_ticket, &ticket_expect, &ticket_setiflocked, true /*strong*/, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE))
{
lock->m_depth = 1;
__atomic_store_4(&lock->m_pidOwner, gettid(), __ATOMIC_RELEASE);
__sync_synchronize();
return true;
}
return false;
}
extern "C" void fastlock_unlock(struct fastlock *lock)
{
--lock->m_depth;
@ -90,7 +117,7 @@ extern "C" void fastlock_unlock(struct fastlock *lock)
{
lock->m_pidOwner = -1;
__sync_synchronize();
__atomic_fetch_add(&lock->m_active, 1, __ATOMIC_ACQ_REL);
__atomic_fetch_add(&lock->m_ticket.m_active, 1, __ATOMIC_ACQ_REL);
}
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
@ -8,6 +9,7 @@ extern "C" {
struct fastlock;
void fastlock_init(struct fastlock *lock);
void fastlock_lock(struct fastlock *lock);
int fastlock_trylock(struct fastlock *lock);
void fastlock_unlock(struct fastlock *lock);
void fastlock_free(struct fastlock *lock);
@ -16,10 +18,14 @@ void fastlock_free(struct fastlock *lock);
}
#endif
struct ticket
{
uint16_t m_active;
uint16_t m_avail;
};
struct fastlock
{
volatile unsigned m_active;
volatile unsigned m_avail;
volatile struct ticket m_ticket;
volatile int m_pidOwner;
volatile int m_depth;
@ -35,6 +41,11 @@ struct fastlock
fastlock_lock(this);
}
bool try_lock()
{
return !!fastlock_trylock(this);
}
void unlock()
{
fastlock_unlock(this);