// Copyright (c) 2022 Klemens D. Morgenstern // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_COBALT_WAIT_GROUP_HPP #define BOOST_COBALT_WAIT_GROUP_HPP #include namespace boost::cobalt { // tag::outline[] struct wait_group { // create a wait_group explicit wait_group(asio::cancellation_type normal_cancel = asio::cancellation_type::none, asio::cancellation_type exception_cancel = asio::cancellation_type::all); // insert a task into the group void push_back(promise p); // the number of tasks in the group std::size_t size() const; // remove completed tasks without waiting (i.e. zombie tasks) std::size_t reap(); // cancel all tasks void cancel(asio::cancellation_type ct = asio::cancellation_type::all); // end::outline[] /* tag::outline[] // wait for one task to complete. __wait_one_op__ wait_one(); // wait for all tasks to complete __wait_op__ wait(); // wait for all tasks to complete __wait_op__ operator co_await (); // when used with `with` , this will receive the exception // and wait for the completion // if `ep` is set, this will use the `exception_cancel` level, // otherwise the `normal_cancel` to cancel all promises. __wait_op__ await_exit(std::exception_ptr ep); end::outline[] */ auto wait_one() -> detail::race_wrapper { return detail::race_wrapper(waitables_); } detail::gather_wrapper wait() { return detail::gather_wrapper(waitables_); } detail::gather_wrapper::awaitable_type operator co_await () { return detail::gather_wrapper(waitables_).operator co_await(); } // swallow the exception here. detail::gather_wrapper await_exit(std::exception_ptr ep) { auto ct = ep ? ct_except_ : ct_normal_; if (ct != asio::cancellation_type::none) for (auto & w : waitables_) w.cancel(ct); return detail::gather_wrapper(waitables_); } private: std::list> waitables_; asio::cancellation_type ct_normal_, ct_except_; // tag::outline[] }; // end::outline[] inline wait_group::wait_group( asio::cancellation_type normal_cancel, asio::cancellation_type exception_cancel) : ct_normal_(normal_cancel), ct_except_(exception_cancel) {} inline std::size_t wait_group::size() const {return waitables_.size();} inline std::size_t wait_group::reap() { return erase_if(waitables_, [](promise & p) { return p.ready() && p;}); } inline void wait_group::cancel(asio::cancellation_type ct) { for (auto & w : waitables_) w.cancel(ct); } inline void wait_group::push_back(promise p) { waitables_.push_back(std::move(p));} } #endif //BOOST_COBALT_WAIT_GROUP_HPP