]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | ||
19 | /* | |
20 | * author: Niek J Bouman | |
21 | * reviewer: Avi Kivity | |
22 | * November 2021 | |
23 | */ | |
24 | ||
25 | #pragma once | |
26 | ||
27 | #include <iterator> | |
28 | #include <cstddef> | |
29 | #include <type_traits> | |
30 | #include <vector> | |
31 | #include <seastar/core/future.hh> | |
32 | #include <seastar/core/shared_ptr.hh> | |
33 | ||
34 | namespace seastar { | |
35 | ||
36 | template <class Sequence> | |
37 | struct when_any_result { | |
38 | std::size_t index; | |
39 | Sequence futures; | |
40 | }; | |
41 | ||
42 | namespace internal { | |
43 | class waiter { | |
44 | bool _done = false; | |
45 | promise<std::size_t> _promise; | |
46 | ||
47 | public: | |
48 | void done(std::size_t index) { | |
49 | if (!_done) { | |
50 | _done = true; | |
51 | _promise.set_value(index); | |
52 | } | |
53 | } | |
54 | auto get_future() { return _promise.get_future(); } | |
55 | }; | |
56 | ||
57 | } // namespace internal | |
58 | ||
59 | /// Wait for the first of multiple futures to complete (iterator version). | |
60 | /// | |
61 | /// Given a range of futures as input, wait for the first of them | |
62 | /// to resolve (either successfully or with an exception), and return | |
63 | /// all of them in a \c when_any_result (following the concurrency TS from | |
64 | /// the standard library), containing a std::vector to all futures | |
65 | /// and the index (into the vector) of the future that resolved. | |
66 | /// | |
67 | /// \param begin an \c InputIterator designating the beginning of the range of futures | |
68 | /// \param end an \c InputIterator designating the end of the range of futures | |
69 | /// \return a \c when_any_result of all the futures in the input; when | |
70 | /// ready, at least one of the contained futures (the one indicated by index) will be ready. | |
71 | template <class FutureIterator> | |
72 | SEASTAR_CONCEPT( requires requires (FutureIterator i) { { *i++ }; requires is_future<std::remove_reference_t<decltype(*i)>>::value; } ) | |
73 | auto when_any(FutureIterator begin, FutureIterator end) noexcept | |
74 | -> future<when_any_result<std::vector<std::decay_t<typename std::iterator_traits<FutureIterator>::value_type>>>> | |
75 | { | |
76 | using ReturnType = when_any_result<std::vector<typename std::iterator_traits<FutureIterator>::value_type>>; | |
77 | if (begin == end) { | |
78 | return make_ready_future<ReturnType>(); | |
79 | } | |
80 | ReturnType result; | |
81 | result.futures.reserve(std::distance(begin, end)); | |
82 | auto waiter_obj = make_lw_shared<internal::waiter>(); | |
83 | std::size_t index{0}; | |
84 | for (auto it = begin; it != end; ++it) { | |
85 | if (it->available()) { | |
86 | result.futures.push_back(std::move(*it)); | |
87 | waiter_obj->done(index); | |
88 | } else { | |
89 | result.futures.push_back(it->finally([waiter_obj, index] { | |
90 | waiter_obj->done(index); | |
91 | })); | |
92 | } | |
93 | index++; | |
94 | } | |
95 | return waiter_obj->get_future().then( | |
96 | [result = std::move(result)](std::size_t index) mutable { | |
97 | result.index = index; | |
98 | return std::move(result); | |
99 | } | |
100 | ); | |
101 | } | |
102 | } // namespace seastar |