mirror of
https://github.com/matrix-construct/construct
synced 2024-12-01 19:22:53 +01:00
ircd::ctx: Refactor mutexes to reuse ctx::dock for queueing.
This commit is contained in:
parent
8cbb354c64
commit
fe45b08f8a
2 changed files with 91 additions and 98 deletions
|
@ -14,8 +14,6 @@
|
||||||
namespace ircd::ctx
|
namespace ircd::ctx
|
||||||
{
|
{
|
||||||
class mutex;
|
class mutex;
|
||||||
|
|
||||||
template<class queue> void release_sequence(queue &);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -26,7 +24,7 @@ namespace ircd::ctx
|
||||||
class ircd::ctx::mutex
|
class ircd::ctx::mutex
|
||||||
{
|
{
|
||||||
bool m;
|
bool m;
|
||||||
list q;
|
dock q;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool locked() const;
|
bool locked() const;
|
||||||
|
@ -57,6 +55,7 @@ inline
|
||||||
ircd::ctx::mutex::mutex(mutex &&o)
|
ircd::ctx::mutex::mutex(mutex &&o)
|
||||||
noexcept
|
noexcept
|
||||||
:m{std::move(o.m)}
|
:m{std::move(o.m)}
|
||||||
|
,q{std::move(o.q)}
|
||||||
{
|
{
|
||||||
o.m = false;
|
o.m = false;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +67,7 @@ noexcept
|
||||||
{
|
{
|
||||||
this->~mutex();
|
this->~mutex();
|
||||||
m = std::move(o.m);
|
m = std::move(o.m);
|
||||||
|
q = std::move(o.q);
|
||||||
o.m = false;
|
o.m = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -84,19 +84,18 @@ ircd::ctx::mutex::unlock()
|
||||||
{
|
{
|
||||||
assert(m);
|
assert(m);
|
||||||
m = false;
|
m = false;
|
||||||
release_sequence(q);
|
q.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::mutex::lock()
|
ircd::ctx::mutex::lock()
|
||||||
{
|
{
|
||||||
if(likely(try_lock()))
|
q.wait([this]
|
||||||
return;
|
{
|
||||||
|
return !locked();
|
||||||
|
});
|
||||||
|
|
||||||
assert(current);
|
m = true;
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock())
|
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class duration>
|
template<class duration>
|
||||||
|
@ -110,27 +109,24 @@ template<class time_point>
|
||||||
bool
|
bool
|
||||||
ircd::ctx::mutex::try_lock_until(const time_point &tp)
|
ircd::ctx::mutex::try_lock_until(const time_point &tp)
|
||||||
{
|
{
|
||||||
if(likely(try_lock()))
|
const bool success
|
||||||
return true;
|
|
||||||
|
|
||||||
assert(current);
|
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock())
|
|
||||||
{
|
{
|
||||||
if(unlikely(wait_until<std::nothrow_t>(tp)))
|
q.wait_until(tp, [this]
|
||||||
{
|
{
|
||||||
q.remove(current);
|
return !locked();
|
||||||
return false;
|
})
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
if(likely(success))
|
||||||
|
m = true;
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ircd::ctx::mutex::try_lock()
|
ircd::ctx::mutex::try_lock()
|
||||||
{
|
{
|
||||||
if(m)
|
if(locked())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m = true;
|
m = true;
|
||||||
|
@ -150,24 +146,3 @@ const
|
||||||
{
|
{
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class queue>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,9 +20,7 @@ class ircd::ctx::shared_mutex
|
||||||
{
|
{
|
||||||
bool u;
|
bool u;
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
list q;
|
dock q;
|
||||||
|
|
||||||
void release();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool unique() const;
|
bool unique() const;
|
||||||
|
@ -30,6 +28,10 @@ class ircd::ctx::shared_mutex
|
||||||
size_t shares() const;
|
size_t shares() const;
|
||||||
size_t waiting() 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();
|
||||||
bool try_lock_shared();
|
bool try_lock_shared();
|
||||||
bool try_lock_upgrade();
|
bool try_lock_upgrade();
|
||||||
|
@ -86,6 +88,7 @@ ircd::ctx::shared_mutex::shared_mutex(shared_mutex &&o)
|
||||||
noexcept
|
noexcept
|
||||||
:u{std::move(o.u)}
|
:u{std::move(o.u)}
|
||||||
,s{std::move(o.s)}
|
,s{std::move(o.s)}
|
||||||
|
,q{std::move(o.q)}
|
||||||
{
|
{
|
||||||
o.u = false;
|
o.u = false;
|
||||||
o.s = 0;
|
o.s = 0;
|
||||||
|
@ -99,6 +102,7 @@ noexcept
|
||||||
this->~shared_mutex();
|
this->~shared_mutex();
|
||||||
u = std::move(o.u);
|
u = std::move(o.u);
|
||||||
s = std::move(o.s);
|
s = std::move(o.s);
|
||||||
|
q = std::move(o.q);
|
||||||
o.u = false;
|
o.u = false;
|
||||||
o.s = 0;
|
o.s = 0;
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -118,7 +122,7 @@ ircd::ctx::shared_mutex::unlock_upgrade_and_lock_shared()
|
||||||
{
|
{
|
||||||
++s;
|
++s;
|
||||||
u = false;
|
u = false;
|
||||||
release();
|
q.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
|
@ -139,28 +143,28 @@ inline void
|
||||||
ircd::ctx::shared_mutex::unlock_and_lock_shared()
|
ircd::ctx::shared_mutex::unlock_and_lock_shared()
|
||||||
{
|
{
|
||||||
s = 1;
|
s = 1;
|
||||||
release();
|
q.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::unlock_upgrade()
|
ircd::ctx::shared_mutex::unlock_upgrade()
|
||||||
{
|
{
|
||||||
u = false;
|
u = false;
|
||||||
release();
|
q.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::unlock_shared()
|
ircd::ctx::shared_mutex::unlock_shared()
|
||||||
{
|
{
|
||||||
--s;
|
--s;
|
||||||
release();
|
q.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::unlock()
|
ircd::ctx::shared_mutex::unlock()
|
||||||
{
|
{
|
||||||
s = 0;
|
s = 0;
|
||||||
release();
|
q.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class duration>
|
template<class duration>
|
||||||
|
@ -241,37 +245,34 @@ ircd::ctx::shared_mutex::try_unlock_shared_and_lock()
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::lock_upgrade()
|
ircd::ctx::shared_mutex::lock_upgrade()
|
||||||
{
|
{
|
||||||
if(likely(try_lock_upgrade()))
|
q.wait([this]
|
||||||
return;
|
{
|
||||||
|
return can_lock_upgrade();
|
||||||
|
});
|
||||||
|
|
||||||
assert(current);
|
u = true;
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock_upgrade())
|
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::lock_shared()
|
ircd::ctx::shared_mutex::lock_shared()
|
||||||
{
|
{
|
||||||
if(likely(try_lock_shared()))
|
q.wait([this]
|
||||||
return;
|
{
|
||||||
|
return can_lock_shared();
|
||||||
|
});
|
||||||
|
|
||||||
assert(current);
|
++s;
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock_shared())
|
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ircd::ctx::shared_mutex::lock()
|
ircd::ctx::shared_mutex::lock()
|
||||||
{
|
{
|
||||||
if(likely(try_lock()))
|
q.wait([this]
|
||||||
return;
|
{
|
||||||
|
return can_lock();
|
||||||
|
});
|
||||||
|
|
||||||
assert(current);
|
s = std::numeric_limits<decltype(s)>::min();
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock())
|
|
||||||
wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class duration>
|
template<class duration>
|
||||||
|
@ -315,34 +316,29 @@ template<class time_point>
|
||||||
bool
|
bool
|
||||||
ircd::ctx::shared_mutex::try_lock_until(time_point&& tp)
|
ircd::ctx::shared_mutex::try_lock_until(time_point&& tp)
|
||||||
{
|
{
|
||||||
if(likely(try_lock()))
|
const bool can_lock
|
||||||
return true;
|
|
||||||
|
|
||||||
assert(current);
|
|
||||||
q.push_back(current);
|
|
||||||
while(!try_lock())
|
|
||||||
{
|
{
|
||||||
if(unlikely(wait_until<std::nothrow_t>(tp)))
|
q.wait_until(tp, [this]
|
||||||
{
|
{
|
||||||
q.remove(current);
|
return this->can_lock();
|
||||||
return false;
|
})
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
if(can_lock)
|
||||||
|
s = std::numeric_limits<decltype(s)>::min();
|
||||||
|
|
||||||
|
return can_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ircd::ctx::shared_mutex::try_lock_upgrade()
|
ircd::ctx::shared_mutex::try_lock_upgrade()
|
||||||
{
|
{
|
||||||
if(s < 0)
|
if(can_lock_upgrade())
|
||||||
return false;
|
{
|
||||||
|
|
||||||
if(u)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
u = true;
|
u = true;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -355,11 +351,39 @@ ircd::ctx::shared_mutex::try_lock_shared()
|
||||||
inline bool
|
inline bool
|
||||||
ircd::ctx::shared_mutex::try_lock()
|
ircd::ctx::shared_mutex::try_lock()
|
||||||
{
|
{
|
||||||
if(s)
|
if(can_lock())
|
||||||
return false;
|
{
|
||||||
|
|
||||||
s = std::numeric_limits<decltype(s)>::min();
|
s = std::numeric_limits<decltype(s)>::min();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
ircd::ctx::shared_mutex::can_lock_upgrade()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if(s < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(u)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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
|
inline size_t
|
||||||
|
@ -389,9 +413,3 @@ const
|
||||||
{
|
{
|
||||||
return s == std::numeric_limits<decltype(s)>::min();
|
return s == std::numeric_limits<decltype(s)>::min();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
|
||||||
ircd::ctx::shared_mutex::release()
|
|
||||||
{
|
|
||||||
release_sequence(q);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue