diff --git a/include/ircd/ctx/mutex.h b/include/ircd/ctx/mutex.h index 57b8b7ed6..68e4b5fd0 100644 --- a/include/ircd/ctx/mutex.h +++ b/include/ircd/ctx/mutex.h @@ -14,8 +14,6 @@ namespace ircd::ctx { class mutex; - - template void release_sequence(queue &); } // @@ -26,7 +24,7 @@ namespace ircd::ctx class ircd::ctx::mutex { bool m; - list q; + dock q; public: bool locked() const; @@ -57,6 +55,7 @@ inline ircd::ctx::mutex::mutex(mutex &&o) noexcept :m{std::move(o.m)} +,q{std::move(o.q)} { o.m = false; } @@ -68,6 +67,7 @@ noexcept { this->~mutex(); m = std::move(o.m); + q = std::move(o.q); o.m = false; return *this; } @@ -84,19 +84,18 @@ ircd::ctx::mutex::unlock() { assert(m); m = false; - release_sequence(q); + q.notify_one(); } inline void ircd::ctx::mutex::lock() { - if(likely(try_lock())) - return; + q.wait([this] + { + return !locked(); + }); - assert(current); - q.push_back(current); - while(!try_lock()) - wait(); + m = true; } template @@ -110,27 +109,24 @@ template bool ircd::ctx::mutex::try_lock_until(const time_point &tp) { - if(likely(try_lock())) - return true; - - assert(current); - q.push_back(current); - while(!try_lock()) + const bool success { - if(unlikely(wait_until(tp))) + q.wait_until(tp, [this] { - q.remove(current); - return false; - } - } + return !locked(); + }) + }; - return true; + if(likely(success)) + m = true; + + return success; } inline bool ircd::ctx::mutex::try_lock() { - if(m) + if(locked()) return false; m = true; @@ -150,24 +146,3 @@ const { return m; } - -template -void -ircd::ctx::release_sequence(queue &q) -{ - assert(current); - - ctx *next; do - { - if(!q.empty()) - { - next = q.front(); - q.pop_front(); - } - else next = nullptr; - } - while(next == current); - - if(next) - yield(*next); -} diff --git a/include/ircd/ctx/shared_mutex.h b/include/ircd/ctx/shared_mutex.h index 008390273..a2be8ecc1 100644 --- a/include/ircd/ctx/shared_mutex.h +++ b/include/ircd/ctx/shared_mutex.h @@ -20,9 +20,7 @@ class ircd::ctx::shared_mutex { bool u; ssize_t s; - list q; - - void release(); + dock q; public: bool unique() const; @@ -30,6 +28,10 @@ class ircd::ctx::shared_mutex size_t shares() const; size_t waiting() const; + bool can_lock() const; + bool can_lock_shared() const; + bool can_lock_upgrade() const; + bool try_lock(); bool try_lock_shared(); bool try_lock_upgrade(); @@ -86,6 +88,7 @@ ircd::ctx::shared_mutex::shared_mutex(shared_mutex &&o) noexcept :u{std::move(o.u)} ,s{std::move(o.s)} +,q{std::move(o.q)} { o.u = false; o.s = 0; @@ -99,6 +102,7 @@ noexcept this->~shared_mutex(); u = std::move(o.u); s = std::move(o.s); + q = std::move(o.q); o.u = false; o.s = 0; return *this; @@ -118,7 +122,7 @@ ircd::ctx::shared_mutex::unlock_upgrade_and_lock_shared() { ++s; u = false; - release(); + q.notify_one(); } inline void @@ -139,28 +143,28 @@ inline void ircd::ctx::shared_mutex::unlock_and_lock_shared() { s = 1; - release(); + q.notify_one(); } inline void ircd::ctx::shared_mutex::unlock_upgrade() { u = false; - release(); + q.notify_one(); } inline void ircd::ctx::shared_mutex::unlock_shared() { --s; - release(); + q.notify_one(); } inline void ircd::ctx::shared_mutex::unlock() { s = 0; - release(); + q.notify_all(); } template @@ -241,37 +245,34 @@ ircd::ctx::shared_mutex::try_unlock_shared_and_lock() inline void ircd::ctx::shared_mutex::lock_upgrade() { - if(likely(try_lock_upgrade())) - return; + q.wait([this] + { + return can_lock_upgrade(); + }); - assert(current); - q.push_back(current); - while(!try_lock_upgrade()) - wait(); + u = true; } inline void ircd::ctx::shared_mutex::lock_shared() { - if(likely(try_lock_shared())) - return; + q.wait([this] + { + return can_lock_shared(); + }); - assert(current); - q.push_back(current); - while(!try_lock_shared()) - wait(); + ++s; } inline void ircd::ctx::shared_mutex::lock() { - if(likely(try_lock())) - return; + q.wait([this] + { + return can_lock(); + }); - assert(current); - q.push_back(current); - while(!try_lock()) - wait(); + s = std::numeric_limits::min(); } template @@ -315,34 +316,29 @@ template bool ircd::ctx::shared_mutex::try_lock_until(time_point&& tp) { - if(likely(try_lock())) - return true; - - assert(current); - q.push_back(current); - while(!try_lock()) + const bool can_lock { - if(unlikely(wait_until(tp))) + q.wait_until(tp, [this] { - q.remove(current); - return false; - } - } + return this->can_lock(); + }) + }; - return true; + if(can_lock) + s = std::numeric_limits::min(); + + return can_lock; } inline bool ircd::ctx::shared_mutex::try_lock_upgrade() { - if(s < 0) - return false; - - if(u) - return false; - - u = true; - return true; + if(can_lock_upgrade()) + { + u = true; + return true; + } + else return false; } inline bool @@ -355,13 +351,41 @@ ircd::ctx::shared_mutex::try_lock_shared() inline bool ircd::ctx::shared_mutex::try_lock() { - if(s) + if(can_lock()) + { + s = std::numeric_limits::min(); + return true; + } + else return false; +} + +inline bool +ircd::ctx::shared_mutex::can_lock_upgrade() +const +{ + if(s < 0) + return false; + + if(u) return false; - s = std::numeric_limits::min(); return true; } +inline bool +ircd::ctx::shared_mutex::can_lock_shared() +const +{ + return s >= 0; +} + +inline bool +ircd::ctx::shared_mutex::can_lock() +const +{ + return s == 0; +} + inline size_t ircd::ctx::shared_mutex::waiting() const @@ -389,9 +413,3 @@ const { return s == std::numeric_limits::min(); } - -inline void -ircd::ctx::shared_mutex::release() -{ - release_sequence(q); -}