0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-02 01:59:33 +02:00

ircd::ctx::dock: Eliminate inlined template complex; optimize linkages.

This commit is contained in:
Jason Volk 2022-06-29 13:03:04 -07:00
parent 29b0523dfc
commit 8b6679c5e9
3 changed files with 175 additions and 160 deletions

View file

@ -34,11 +34,11 @@ class ircd::ctx::dock
size_t size() const noexcept;
bool waiting(const ctx &) const noexcept;
template<class time_point> bool wait_until(time_point&&, const predicate &);
template<class time_point> bool wait_until(time_point&&);
bool wait_until(const system_point, const predicate &);
bool wait_until(const system_point);
template<class duration> bool wait_for(const duration &, const predicate &);
template<class duration> bool wait_for(const duration &);
template<class duration> bool wait_for(const duration, const predicate &);
template<class duration> bool wait_for(const duration);
void wait(const predicate &);
void wait();
@ -50,6 +50,57 @@ class ircd::ctx::dock
void notify() noexcept;
};
namespace ircd::ctx
{
template<> bool dock::wait_for(const microseconds, const predicate &);
template<> bool dock::wait_for(const microseconds);
}
/// Wake up the next context waiting on the dock
inline void
ircd::ctx::dock::notify_one()
noexcept
{
if(q.empty())
return;
ircd::ctx::notify(*q.front());
}
template<class duration>
inline bool
ircd::ctx::dock::wait_for(const duration dur,
const predicate &pred)
{
static_assert(!std::is_same<duration, microseconds>());
return wait_for(duration_cast<microseconds>(dur), pred);
}
template<class duration>
inline bool
ircd::ctx::dock::wait_for(const duration dur)
{
static_assert(!std::is_same<duration, microseconds>());
return wait_for(duration_cast<microseconds>(dur));
}
/// The number of contexts waiting in the queue.
inline size_t
ircd::ctx::dock::size()
const noexcept
{
return q.size();
}
/// The number of contexts waiting in the queue.
inline bool
ircd::ctx::dock::empty()
const noexcept
{
return q.empty();
}
inline void
ircd::ctx::notify(dock &dock)
noexcept
@ -70,134 +121,3 @@ noexcept
{
dock.terminate_all();
}
//
// dock::dock
//
/// Wake up the next context waiting on the dock
inline void
ircd::ctx::dock::notify_one()
noexcept
{
if(q.empty())
return;
ircd::ctx::notify(*q.front());
}
/// Returns true if notified; false if timed out
template<class duration>
inline bool
ircd::ctx::dock::wait_for(const duration &dur)
{
static const duration zero(0);
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
return ircd::ctx::wait<std::nothrow_t>(dur) > zero;
}
/// Returns true if predicate passed; false if timed out
template<class duration>
inline bool
ircd::ctx::dock::wait_for(const duration &dur,
const predicate &pred)
{
static const duration zero(0);
if(pred())
return true;
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
const bool expired
{
ircd::ctx::wait<std::nothrow_t>(dur) <= zero
};
if(pred())
return true;
if(expired)
return false;
}
while(1);
}
/// Returns true if notified; false if timed out
template<class time_point>
inline bool
ircd::ctx::dock::wait_until(time_point&& tp)
{
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
return !ircd::ctx::wait_until<std::nothrow_t>(tp);
}
/// Returns true if predicate passed; false if timed out
template<class time_point>
inline bool
ircd::ctx::dock::wait_until(time_point&& tp,
const predicate &pred)
{
if(pred())
return true;
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
const bool expired
{
ircd::ctx::wait_until<std::nothrow_t>(tp)
};
if(pred())
return true;
if(expired)
return false;
}
while(1);
}

View file

@ -45,10 +45,10 @@ namespace ircd::ctx { inline namespace this_ctx
/// exception (= timeout) is thrown.
/// interruption point.
template<class E>
ircd::throw_overload<E>
inline ircd::throw_overload<E>
ircd::ctx::this_ctx::wait_until(const system_point &tp)
{
if(wait_until<std::nothrow_t>(tp))
if(unlikely(wait_until<std::nothrow_t>(tp)))
throw E{};
}
@ -56,7 +56,7 @@ ircd::ctx::this_ctx::wait_until(const system_point &tp)
/// then returns true. If there's never a notification then returns false.
/// interruption point. this is not noexcept.
template<class E>
ircd::nothrow_overload<E, bool>
inline ircd::nothrow_overload<E, bool>
ircd::ctx::this_ctx::wait_until(const system_point &tp)
{
return wait_until(tp, std::nothrow);
@ -68,7 +68,7 @@ ircd::ctx::this_ctx::wait_until(const system_point &tp)
/// interruption point
template<class E,
class duration>
ircd::throw_overload<E, duration>
inline ircd::throw_overload<E, duration>
ircd::ctx::this_ctx::wait(const duration &d)
{
const auto ret
@ -76,9 +76,10 @@ ircd::ctx::this_ctx::wait(const duration &d)
wait<std::nothrow_t>(d)
};
return ret <= duration(0)?
throw E{}:
ret;
if(unlikely(ret <= duration(0)))
throw E{};
return ret;
}
/// Wait for a notification for some amount of time. This function returns
@ -87,7 +88,7 @@ ircd::ctx::this_ctx::wait(const duration &d)
/// interruption point. this is not noexcept.
template<class E,
class duration>
ircd::nothrow_overload<E, duration>
inline ircd::nothrow_overload<E, duration>
ircd::ctx::this_ctx::wait(const duration &d)
{
const auto ret

View file

@ -2837,7 +2837,6 @@ noexcept
});
}
[[gnu::hot]]
void
ircd::ctx::dock::wait()
{
@ -2880,6 +2879,117 @@ ircd::ctx::dock::wait(const predicate &pred)
while(!pred());
}
template<>
bool
ircd::ctx::dock::wait_for(const microseconds dur)
{
static const microseconds zero {0};
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
return ircd::ctx::wait<std::nothrow_t>(dur) > zero;
}
template<>
bool
ircd::ctx::dock::wait_for(const microseconds dur,
const predicate &pred)
{
static const microseconds zero {0};
if(pred())
return true;
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
const bool expired
{
ircd::ctx::wait<std::nothrow_t>(dur) <= zero
};
if(pred())
return true;
if(expired)
return false;
}
while(1);
}
bool
ircd::ctx::dock::wait_until(const system_point tp)
{
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current);
return !ircd::ctx::wait_until<std::nothrow_t>(tp);
}
/// Returns true if predicate passed; false if timed out
bool
ircd::ctx::dock::wait_until(const system_point tp,
const predicate &pred)
{
if(pred())
return true;
assert(current);
const unwind_exceptional renotify{[this]
{
notify_one();
}};
const unwind remove{[this]
{
q.remove(current);
}};
q.push_back(current); do
{
const bool expired
{
ircd::ctx::wait_until<std::nothrow_t>(tp)
};
if(pred())
return true;
if(expired)
return false;
}
while(1);
}
/// The number of contexts waiting in the queue.
bool
ircd::ctx::dock::waiting(const ctx &a)
@ -2894,22 +3004,6 @@ const noexcept
}});
}
/// The number of contexts waiting in the queue.
size_t
ircd::ctx::dock::size()
const noexcept
{
return q.size();
}
/// The number of contexts waiting in the queue.
bool
ircd::ctx::dock::empty()
const noexcept
{
return q.empty();
}
///////////////////////////////////////////////////////////////////////////////
//
// ctx_list.h