diff --git a/src/ae.cpp b/src/ae.cpp index 9da888118..dd0ff3a32 100644 --- a/src/ae.cpp +++ b/src/ae.cpp @@ -774,6 +774,11 @@ void aeAcquireLock() g_lock.lock(); } +int aeTryAcquireLock() +{ + return g_lock.try_lock(); +} + void aeReleaseLock() { g_lock.unlock(); diff --git a/src/ae.h b/src/ae.h index f1aa0380c..f08c49dd8 100644 --- a/src/ae.h +++ b/src/ae.h @@ -159,6 +159,7 @@ int aeGetSetSize(aeEventLoop *eventLoop); int aeResizeSetSize(aeEventLoop *eventLoop, int setsize); void aeAcquireLock(); +int aeTryAcquireLock(); void aeReleaseLock(); int aeThreadOwnsLock(); diff --git a/src/fastlock.cpp b/src/fastlock.cpp index 72ddb3749..189ef07ab 100644 --- a/src/fastlock.cpp +++ b/src/fastlock.cpp @@ -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); } } diff --git a/src/fastlock.h b/src/fastlock.h index 4ee78635e..b5a70c530 100644 --- a/src/fastlock.h +++ b/src/fastlock.h @@ -1,4 +1,5 @@ #pragma once +#include #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); diff --git a/src/scripting.c b/src/scripting.cpp similarity index 100% rename from src/scripting.c rename to src/scripting.cpp