diff --git a/beast/asio/enable_wait_for_async.h b/beast/asio/enable_wait_for_async.h index 2ba0a796da..84f163b410 100644 --- a/beast/asio/enable_wait_for_async.h +++ b/beast/asio/enable_wait_for_async.h @@ -21,14 +21,12 @@ #define BEAST_ASIO_ENABLE_WAIT_FOR_ASYNC_H_INCLUDED #include - #include - #include #include #include - #include +#include #include #include #include // @@ -50,46 +48,19 @@ private: bool m_continuation; public: - ref_counted_wrapped_handler (Owner& owner, - Handler&& handler, bool continuation) - : m_handler (std::move (handler)) - , m_owner (owner) - , m_continuation (continuation ? true : - boost_asio_handler_cont_helpers::is_continuation (m_handler)) - { - m_owner.get().increment(); - } + ~ref_counted_wrapped_handler(); ref_counted_wrapped_handler (Owner& owner, - Handler const& handler, bool continuation) - : m_handler (handler) - , m_owner (owner) - , m_continuation (continuation ? true : - boost_asio_handler_cont_helpers::is_continuation (m_handler)) - { - m_owner.get().increment(); - } + Handler&& handler, bool continuation); - ~ref_counted_wrapped_handler () - { - m_owner.get().decrement(); - } + ref_counted_wrapped_handler (Owner& owner, + Handler const& handler, bool continuation); - ref_counted_wrapped_handler (ref_counted_wrapped_handler const& other) - : m_handler (other.m_handler) - , m_owner (other.m_owner) - , m_continuation (other.m_continuation) - { - m_owner.get().increment(); - } + ref_counted_wrapped_handler ( + ref_counted_wrapped_handler const& other); - ref_counted_wrapped_handler (ref_counted_wrapped_handler&& other) - : m_handler (std::move (other.m_handler)) - , m_owner (other.m_owner) - , m_continuation (other.m_continuation) - { - m_owner.get().increment(); - } + ref_counted_wrapped_handler ( + ref_counted_wrapped_handler&& other); ref_counted_wrapped_handler& operator= ( ref_counted_wrapped_handler const&) = delete; @@ -154,6 +125,54 @@ public: } }; +template +ref_counted_wrapped_handler::~ref_counted_wrapped_handler() +{ + m_owner.get().decrement(); +} + +template +ref_counted_wrapped_handler::ref_counted_wrapped_handler ( + Owner& owner, Handler&& handler, bool continuation) + : m_handler (std::move (handler)) + , m_owner (owner) + , m_continuation (continuation ? true : + boost_asio_handler_cont_helpers::is_continuation (m_handler)) +{ + m_owner.get().increment(); +} + +template +ref_counted_wrapped_handler::ref_counted_wrapped_handler ( + Owner& owner, Handler const& handler, bool continuation) + : m_handler (handler) + , m_owner (owner) + , m_continuation (continuation ? true : + boost_asio_handler_cont_helpers::is_continuation (m_handler)) +{ + m_owner.get().increment(); +} + +template +ref_counted_wrapped_handler::ref_counted_wrapped_handler ( + ref_counted_wrapped_handler const& other) + : m_handler (other.m_handler) + , m_owner (other.m_owner) + , m_continuation (other.m_continuation) +{ + m_owner.get().increment(); +} + +template +ref_counted_wrapped_handler::ref_counted_wrapped_handler ( + ref_counted_wrapped_handler&& other) + : m_handler (std::move (other.m_handler)) + , m_owner (other.m_owner) + , m_continuation (other.m_continuation) +{ + m_owner.get().increment(); +} + } //------------------------------------------------------------------------------ @@ -259,6 +278,91 @@ protected: /** @} */ }; +//------------------------------------------------------------------------------ + +/** A waitable event object that blocks when handlers are pending. */ +class pending_handlers +{ +private: + std::size_t count_ = 0; + std::mutex mutex_; + std::condition_variable cond_; + + template + friend class detail::ref_counted_wrapped_handler; + + template + void + increment(); + + template + void + decrement(); + +public: + ~pending_handlers() + { + assert (count_ == 0); + } + + template + void + wait(); + + /** Returns a handler that causes wait to block until completed. + The returned handler provides the same execution + guarantees as the passed handler. + */ + /** @{ */ + template + detail::ref_counted_wrapped_handler > + wrap (Handler&& handler, + bool continuation = false) + { + return detail::ref_counted_wrapped_handler > (*this, + std::forward(handler), continuation); + } + + template + detail::ref_counted_wrapped_handler > + wrap (continuation_t, Handler&& handler) + { + return detail::ref_counted_wrapped_handler > (*this, + std::forward(handler), true); + } + /** @} */ +}; + +template +void +pending_handlers::increment() +{ + std::lock_guard lock (mutex_); + ++count_; +} + +template +void +pending_handlers::decrement() +{ + std::lock_guard lock (mutex_); + if (--count_ == 0) + cond_.notify_all(); +} + +template +void +pending_handlers::wait() +{ + std::unique_lock lock (mutex_); + while (count_ != 0) + cond_.wait (lock); +} + } }