1//
2// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8#ifndef BOOST_COBALT_DETAIL_WAIT_GROUP_HPP
9#define BOOST_COBALT_DETAIL_WAIT_GROUP_HPP
10
11#include <boost/cobalt/promise.hpp>
12#include <boost/cobalt/race.hpp>
13#include <boost/cobalt/gather.hpp>
14
15#include <list>
16
17
18namespace boost::cobalt::detail
19{
20
21struct race_wrapper
22{
23 using impl_type = decltype(race(p&: std::declval<std::list<promise<void>> &>()));
24 std::list<promise<void>> &waitables_;
25
26 race_wrapper(std::list<promise<void>> &waitables) : waitables_(waitables)
27 {
28 }
29
30 struct awaitable_type
31 {
32
33 bool await_ready()
34 {
35 if (waitables_.empty())
36 return true;
37 else
38 return impl_->await_ready();
39 }
40
41 template<typename Promise>
42 auto await_suspend(std::coroutine_handle<Promise> h)
43 {
44 return impl_->await_suspend(h);
45 }
46
47 void await_resume()
48 {
49 if (waitables_.empty())
50 return;
51 auto idx = impl_->await_resume();
52 if (idx != std::numeric_limits<std::size_t>::max())
53 waitables_.erase(position: std::next(x: waitables_.begin(), n: idx));
54 }
55
56 awaitable_type(std::list<promise<void>> &waitables) : waitables_(waitables)
57 {
58 if (!waitables_.empty())
59 impl_.emplace(args&: waitables_, args&: random_);
60 }
61
62 private:
63 std::optional<impl_type::awaitable> impl_;
64 std::list<promise<void>> &waitables_;
65 std::default_random_engine &random_{detail::prng()};
66
67 };
68 awaitable_type operator co_await() &&
69 {
70 return awaitable_type(waitables_);
71 }
72};
73
74struct gather_wrapper
75{
76 using impl_type = decltype(gather(p&: std::declval<std::list<promise<void>> &>()));
77 std::list<promise<void>> &waitables_;
78
79 gather_wrapper(std::list<promise<void>> &waitables) : waitables_(waitables)
80 {
81 }
82
83 struct awaitable_type
84 {
85 bool await_ready()
86 {
87 if (waitables_.empty())
88 return true;
89 else
90 return impl_->await_ready();
91 }
92
93 template<typename Promise>
94 auto await_suspend(std::coroutine_handle<Promise> h)
95 {
96 return impl_->await_suspend(h);
97 }
98
99 void await_resume()
100 {
101 if (waitables_.empty())
102 return;
103 BOOST_ASSERT(impl_);
104 impl_->await_resume();
105 waitables_.clear();
106 }
107
108 awaitable_type(std::list<promise<void>> &waitables) : waitables_(waitables)
109 {
110 if (!waitables_.empty())
111 impl_.emplace(args&: waitables_);
112 }
113 private:
114 std::list<promise<void>> &waitables_;
115 std::optional<decltype(gather(p&: waitables_).operator co_await())> impl_;
116 };
117
118 awaitable_type operator co_await()
119 {
120 return awaitable_type(waitables_);
121 }
122
123};
124
125}
126
127#endif //BOOST_COBALT_DETAIL_WAIT_GROUP_HPP
128

source code of boost/libs/cobalt/include/boost/cobalt/detail/wait_group.hpp