diff --git a/include/ircd/ctx/dock.h b/include/ircd/ctx/dock.h index 90420522b..10859992d 100644 --- a/include/ircd/ctx/dock.h +++ b/include/ircd/ctx/dock.h @@ -25,6 +25,7 @@ namespace ircd::ctx /// class ircd::ctx::dock { + struct continuation; using predicate = std::function; list q; @@ -56,6 +57,15 @@ namespace ircd::ctx template<> bool dock::wait_for(const microseconds); } +struct [[gnu::visibility("internal")]] +ircd::ctx::dock::continuation +{ + dock *const d; + + continuation(dock *); + ~continuation() noexcept; +}; + /// Wake up the next context waiting on the dock inline void ircd::ctx::dock::notify_one() diff --git a/ircd/ctx.cc b/ircd/ctx.cc index bab751879..e7da4f41e 100644 --- a/ircd/ctx.cc +++ b/ircd/ctx.cc @@ -2863,18 +2863,7 @@ noexcept void ircd::ctx::dock::wait() { - assert(current); - const unwind_exceptional renotify{[this] - { - notify_one(); - }}; - - const unwind remove{[this] - { - q.remove(current); - }}; - - q.push_back(current); + const continuation c{this}; this_ctx::wait(); } @@ -2884,18 +2873,7 @@ ircd::ctx::dock::wait(const predicate &pred) if(pred()) return; - assert(current); - const unwind_exceptional renotify{[this] - { - notify_one(); - }}; - - const unwind remove{[this] - { - q.remove(current); - }}; - - q.push_back(current); do + const continuation c{this}; do { this_ctx::wait(); } @@ -2908,18 +2886,7 @@ 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); + const continuation c{this}; return ircd::ctx::wait(dur) > zero; } @@ -2933,18 +2900,7 @@ ircd::ctx::dock::wait_for(const microseconds dur, 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 continuation c{this}; do { const bool expired { @@ -2963,18 +2919,7 @@ ircd::ctx::dock::wait_for(const microseconds dur, 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); + const continuation c{this}; return !ircd::ctx::wait_until(tp); } @@ -2986,18 +2931,7 @@ ircd::ctx::dock::wait_until(const system_point tp, 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 continuation c{this}; do { const bool expired { @@ -3027,6 +2961,31 @@ const noexcept }}); } +// +// dock::continuation +// + +ircd::ctx::dock::continuation::continuation(dock *const d) +:d{d} +{ + assert(d); + assert(current); + + d->q.push_back(current); +} + +ircd::ctx::dock::continuation::~continuation() +noexcept +{ + assert(d); + assert(current); + + d->q.remove(current); + + if(unlikely(std::uncaught_exceptions())) + d->notify_one(); +} + /////////////////////////////////////////////////////////////////////////////// // // ctx_list.h