wait_group.hpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_COBALT_WAIT_GROUP_HPP
  6. #define BOOST_COBALT_WAIT_GROUP_HPP
  7. #include <boost/cobalt/detail/wait_group.hpp>
  8. namespace boost::cobalt
  9. {
  10. // tag::outline[]
  11. struct wait_group
  12. {
  13. // create a wait_group
  14. explicit
  15. wait_group(asio::cancellation_type normal_cancel = asio::cancellation_type::none,
  16. asio::cancellation_type exception_cancel = asio::cancellation_type::all);
  17. // insert a task into the group
  18. void push_back(promise<void> p);
  19. // the number of tasks in the group
  20. std::size_t size() const;
  21. // remove completed tasks without waiting (i.e. zombie tasks)
  22. std::size_t reap();
  23. // cancel all tasks
  24. void cancel(asio::cancellation_type ct = asio::cancellation_type::all);
  25. // end::outline[]
  26. /* tag::outline[]
  27. // wait for one task to complete.
  28. __wait_one_op__ wait_one();
  29. // wait for all tasks to complete
  30. __wait_op__ wait();
  31. // wait for all tasks to complete
  32. __wait_op__ operator co_await ();
  33. // when used with `with` , this will receive the exception
  34. // and wait for the completion
  35. // if `ep` is set, this will use the `exception_cancel` level,
  36. // otherwise the `normal_cancel` to cancel all promises.
  37. __wait_op__ await_exit(std::exception_ptr ep);
  38. end::outline[] */
  39. auto wait_one() -> detail::race_wrapper
  40. {
  41. return detail::race_wrapper(waitables_);
  42. }
  43. detail::gather_wrapper wait()
  44. {
  45. return detail::gather_wrapper(waitables_);
  46. }
  47. detail::gather_wrapper::awaitable_type operator co_await ()
  48. {
  49. return detail::gather_wrapper(waitables_).operator co_await();
  50. }
  51. // swallow the exception here.
  52. detail::gather_wrapper await_exit(std::exception_ptr ep)
  53. {
  54. auto ct = ep ? ct_except_ : ct_normal_;
  55. if (ct != asio::cancellation_type::none)
  56. for (auto & w : waitables_)
  57. w.cancel(ct);
  58. return detail::gather_wrapper(waitables_);
  59. }
  60. private:
  61. std::list<promise<void>> waitables_;
  62. asio::cancellation_type ct_normal_, ct_except_;
  63. // tag::outline[]
  64. };
  65. // end::outline[]
  66. inline wait_group::wait_group(
  67. asio::cancellation_type normal_cancel,
  68. asio::cancellation_type exception_cancel)
  69. : ct_normal_(normal_cancel), ct_except_(exception_cancel) {}
  70. inline
  71. std::size_t wait_group::size() const {return waitables_.size();}
  72. inline
  73. std::size_t wait_group::reap()
  74. {
  75. return erase_if(waitables_, [](promise<void> & p) { return p.ready() && p;});
  76. }
  77. inline
  78. void wait_group::cancel(asio::cancellation_type ct)
  79. {
  80. for (auto & w : waitables_)
  81. w.cancel(ct);
  82. }
  83. inline
  84. void wait_group::push_back(promise<void> p) { waitables_.push_back(std::move(p));}
  85. }
  86. #endif //BOOST_COBALT_WAIT_GROUP_HPP