• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #863

11 Jan 2023 05:02PM UTC coverage: 86.533% (-0.05%) from 86.582%
#863

push

StellarBot
Merge #6126

6126: Deprecate hpx::parallel::task_block in favor of hpx::experimental::ta… r=hkaiser a=dimitraka



Co-authored-by: kadimitra <kadimitra@ece.auth.gr>

174614 of 201789 relevant lines covered (86.53%)

1954694.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.52
/libs/core/async_combinators/include/hpx/async_combinators/split_future.hpp
1
//  Copyright (c) 2016-2022 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
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
/// \file hpx/async_combinators/split_future.hpp
8

9
#pragma once
10

11
#if defined(DOXYGEN)
12
namespace hpx {
13
    /// The function \a split_future is an operator allowing to split a given
14
    /// future of a sequence of values (any tuple, std::pair, or std::array)
15
    /// into an equivalent container of futures where each future represents
16
    /// one of the values from the original future. In some sense this function
17
    /// provides the inverse operation of \a when_all.
18
    ///
19
    /// \param f    [in] A future holding an arbitrary sequence of values stored
20
    ///             in a tuple-like container. This facility supports
21
    ///             \a hpx::tuple<>, \a std::pair<T1, T2>, and
22
    ///             \a std::array<T, N>
23
    ///
24
    /// \return     Returns an equivalent container (same container type as
25
    ///             passed as the argument) of futures, where each future refers
26
    ///             to the corresponding value in the input parameter. All of
27
    ///             the returned futures become ready once the input future has
28
    ///             become ready. If the input future is exceptional, all output
29
    ///             futures will be exceptional as well.
30
    ///
31
    /// \note       The following cases are special:
32
    /// \code
33
    ///     tuple<future<void> > split_future(future<tuple<> > && f);
34
    ///     array<future<void>, 1> split_future(future<array<T, 0> > && f);
35
    /// \endcode
36
    ///             here the returned futures are directly representing the
37
    ///             futures which were passed to the function.
38
    ///
39
    template <typename... Ts>
40
    inline tuple<future<Ts>...> split_future(future<tuple<Ts...>>&& f);
41

42
    /// The function \a split_future is an operator allowing to split a given
43
    /// future of a sequence of values (any std::vector)
44
    /// into a std::vector of futures where each future represents
45
    /// one of the values from the original std::vector. In some sense this
46
    /// function provides the inverse operation of \a when_all.
47
    ///
48
    /// \param f    [in] A future holding an arbitrary sequence of values stored
49
    ///             in a std::vector.
50
    /// \param size [in] The number of elements the vector will hold once the
51
    ///             input future has become ready
52
    ///
53
    /// \return     Returns a std::vector of futures, where each future refers
54
    ///             to the corresponding value in the input parameter. All of
55
    ///             the returned futures become ready once the input future has
56
    ///             become ready. If the input future is exceptional, all output
57
    ///             futures will be exceptional as well.
58
    ///
59
    template <typename T>
60
    inline std::vector<future<T>> split_future(
61
        future<std::vector<T>>&& f, std::size_t size);
62
}    // namespace hpx
63

64
#else    // DOXYGEN
65

66
#include <hpx/config.hpp>
67
#include <hpx/datastructures/tuple.hpp>
68
#include <hpx/errors/try_catch_exception_ptr.hpp>
69
#include <hpx/functional/deferred_call.hpp>
70
#include <hpx/futures/detail/future_data.hpp>
71
#include <hpx/futures/future.hpp>
72
#include <hpx/futures/packaged_continuation.hpp>
73
#include <hpx/futures/traits/acquire_future.hpp>
74
#include <hpx/futures/traits/acquire_shared_state.hpp>
75
#include <hpx/futures/traits/future_access.hpp>
76
#include <hpx/futures/traits/future_traits.hpp>
77
#include <hpx/modules/errors.hpp>
78
#include <hpx/modules/memory.hpp>
79
#include <hpx/type_support/pack.hpp>
80
#include <hpx/type_support/unused.hpp>
81

82
#include <array>
83
#include <cstddef>
84
#include <exception>
85
#include <tuple>
86
#include <type_traits>
87
#include <utility>
88
#include <vector>
89

90
///////////////////////////////////////////////////////////////////////////////
91
namespace hpx {
92

93
    namespace detail {
94

95
        ///////////////////////////////////////////////////////////////////////
96
        template <typename ContResult>
97
        class split_nth_continuation
69✔
98
          : public lcos::detail::future_data<ContResult>
99
        {
100
            using base_type = lcos::detail::future_data<ContResult>;
101

102
        private:
103
            template <std::size_t I, typename T>
104
            void on_ready(
23✔
105
                traits::detail::shared_state_ptr_for_t<T> const& state)
106
            {
107
                hpx::detail::try_catch_exception_ptr(
23✔
108
                    [&]() {
46✔
109
                        using result_type = traits::future_traits_t<T>;
110
                        result_type* result = state->get_result();
23✔
111
                        this->base_type::set_value(
46✔
112
                            HPX_MOVE(hpx::get<I>(*result)));
23✔
113
                    },
23✔
114
                    [&](std::exception_ptr ep) {
23✔
115
                        this->base_type::set_exception(HPX_MOVE(ep));
×
116
                    });
×
117
            }
23✔
118

119
        public:
120
            template <std::size_t I, typename Future>
121
            void attach(Future& future)
23✔
122
            {
123
                using shared_state_ptr =
124
                    traits::detail::shared_state_ptr_for_t<Future>;
125

126
                // Bind an on_completed handler to this future which will wait
127
                // for the future and will transfer its result to the new
128
                // future.
129
                hpx::intrusive_ptr<split_nth_continuation> this_(this);
23✔
130
                shared_state_ptr const& state =
23✔
131
                    hpx::traits::detail::get_shared_state(future);
23✔
132

133
                state->execute_deferred();
23✔
134
                state->set_on_completed(util::deferred_call(
46✔
135
                    &split_nth_continuation::on_ready<I, Future>,
23✔
136
                    HPX_MOVE(this_), state));
23✔
137
            }
23✔
138
        };
139

140
        ///////////////////////////////////////////////////////////////////////
141
        template <typename Result, typename Tuple, std::size_t I,
142
            typename Future>
143
        inline hpx::traits::detail::shared_state_ptr_t<
144
            typename hpx::tuple_element<I, Tuple>::type>
145
        extract_nth_continuation(Future& future)
23✔
146
        {
147
            using shared_state = split_nth_continuation<Result>;
148

149
            hpx::traits::detail::shared_state_ptr_t<Result> p(
46✔
150
                new shared_state());
23✔
151

152
            static_cast<shared_state*>(p.get())->template attach<I>(future);
23✔
153
            return p;
23✔
154
        }
23✔
155

156
        ///////////////////////////////////////////////////////////////////////
157
        template <std::size_t I, typename Tuple>
158
        HPX_FORCEINLINE hpx::future<typename hpx::tuple_element<I, Tuple>::type>
159
        extract_nth_future(hpx::future<Tuple>& future)
15✔
160
        {
161
            using result_type = typename hpx::tuple_element<I, Tuple>::type;
162

163
            return hpx::traits::future_access<hpx::future<result_type>>::create(
15✔
164
                extract_nth_continuation<result_type, Tuple, I>(future));
15✔
165
        }
×
166

167
        template <std::size_t I, typename Tuple>
168
        HPX_FORCEINLINE hpx::future<typename hpx::tuple_element<I, Tuple>::type>
169
        extract_nth_future(hpx::shared_future<Tuple>& future)
8✔
170
        {
171
            using result_type = typename hpx::tuple_element<I, Tuple>::type;
172

173
            return hpx::traits::future_access<hpx::future<result_type>>::create(
8✔
174
                extract_nth_continuation<result_type, Tuple, I>(future));
8✔
175
        }
×
176

177
        ///////////////////////////////////////////////////////////////////////
178
        template <typename... Ts, std::size_t... Is>
179
        HPX_FORCEINLINE hpx::tuple<hpx::future<Ts>...> split_future_helper(
4✔
180
            hpx::future<hpx::tuple<Ts...>>&& f, hpx::util::index_pack<Is...>)
181
        {
182
            return hpx::make_tuple(extract_nth_future<Is>(f)...);
4✔
183
        }
×
184

185
        template <typename... Ts, std::size_t... Is>
186
        HPX_FORCEINLINE hpx::tuple<hpx::future<Ts>...> split_future_helper(
3✔
187
            hpx::shared_future<hpx::tuple<Ts...>>&& f,
188
            hpx::util::index_pack<Is...>)
189
        {
190
            return hpx::make_tuple(extract_nth_future<Is>(f)...);
3✔
191
        }
×
192

193
        ///////////////////////////////////////////////////////////////////////
194
#if defined(HPX_DATASTRUCTURES_HAVE_ADAPT_STD_TUPLE)
195
        template <typename... Ts, std::size_t... Is>
196
        HPX_FORCEINLINE std::tuple<hpx::future<Ts>...> split_future_helper(
1✔
197
            hpx::future<std::tuple<Ts...>>&& f, hpx::util::index_pack<Is...>)
198
        {
199
            return std::make_tuple(extract_nth_future<Is>(f)...);
1✔
200
        }
×
201

202
        template <typename... Ts, std::size_t... Is>
203
        HPX_FORCEINLINE std::tuple<hpx::future<Ts>...> split_future_helper(
204
            hpx::shared_future<std::tuple<Ts...>>&& f,
205
            hpx::util::index_pack<Is...>)
206
        {
207
            return std::make_tuple(extract_nth_future<Is>(f)...);
208
        }
209
#endif
210

211
        ///////////////////////////////////////////////////////////////////////
212
        template <typename T1, typename T2>
213
        HPX_FORCEINLINE std::pair<hpx::future<T1>, hpx::future<T2>>
214
        split_future_helper(hpx::future<std::pair<T1, T2>>&& f)
2✔
215
        {
216
            return std::make_pair(
2✔
217
                extract_nth_future<0>(f), extract_nth_future<1>(f));
2✔
218
        }
×
219

220
        template <typename T1, typename T2>
221
        HPX_FORCEINLINE std::pair<hpx::future<T1>, hpx::future<T2>>
222
        split_future_helper(hpx::shared_future<std::pair<T1, T2>>&& f)
1✔
223
        {
224
            return std::make_pair(
1✔
225
                extract_nth_future<0>(f), extract_nth_future<1>(f));
1✔
226
        }
×
227

228
        ///////////////////////////////////////////////////////////////////////
229
        template <typename ContResult>
230
        class split_continuation : public lcos::detail::future_data<ContResult>
27✔
231
        {
232
            using base_type = lcos::detail::future_data<ContResult>;
233

234
        private:
235
            template <typename T>
236
            void on_ready(std::size_t i,
9✔
237
                traits::detail::shared_state_ptr_for_t<T> const& state)
238
            {
239
                hpx::detail::try_catch_exception_ptr(
9✔
240
                    [&]() {
18✔
241
                        using result_type = traits::future_traits_t<T>;
242
                        result_type* result = state->get_result();
9✔
243
                        if (i >= result->size())
9✔
244
                        {
245
                            HPX_THROW_EXCEPTION(hpx::error::length_error,
×
246
                                "split_continuation::on_ready",
247
                                "index out of bounds");
248
                        }
249
                        this->base_type::set_value(HPX_MOVE((*result)[i]));
9✔
250
                    },
9✔
251
                    [&](std::exception_ptr ep) {
9✔
252
                        this->base_type::set_exception(HPX_MOVE(ep));
×
253
                    });
×
254
            }
9✔
255

256
        public:
257
            template <typename Future>
258
            void attach(std::size_t i, Future& future)
9✔
259
            {
260
                using shared_state_ptr =
261
                    traits::detail::shared_state_ptr_for_t<Future>;
262

263
                // Bind an on_completed handler to this future which will wait
264
                // for the future and will transfer its result to the new
265
                // future.
266
                hpx::intrusive_ptr<split_continuation> this_(this);
9✔
267
                shared_state_ptr const& state =
9✔
268
                    hpx::traits::detail::get_shared_state(future);
9✔
269

270
                state->execute_deferred();
9✔
271
                state->set_on_completed(
18✔
272
                    util::deferred_call(&split_continuation::on_ready<Future>,
18✔
273
                        HPX_MOVE(this_), i, state));
9✔
274
            }
9✔
275
        };
276

277
        template <typename T, typename Future>
278
        inline hpx::future<T> extract_future_array(
9✔
279
            std::size_t i, Future& future)
280
        {
281
            using shared_state = split_continuation<T>;
282

283
            hpx::traits::detail::shared_state_ptr_t<T> p(new shared_state());
9✔
284

285
            static_cast<shared_state*>(p.get())->attach(i, future);
9✔
286
            return hpx::traits::future_access<hpx::future<T>>::create(p);
9✔
287
        }
9✔
288

289
        template <std::size_t N, typename T, typename Future>
290
        inline std::array<hpx::future<T>, N> split_future_helper_array(
2✔
291
            Future&& f)
292
        {
293
            std::array<hpx::future<T>, N> result;
2✔
294

295
            for (std::size_t i = 0; i != N; ++i)
8✔
296
            {
297
                result[i] = extract_future_array<T>(i, f);
6✔
298
            }
6✔
299

300
            return result;
2✔
301
        }
2✔
302

303
        template <typename T, typename Future>
304
        inline std::vector<hpx::future<T>> split_future_helper_vector(
1✔
305
            Future&& f, std::size_t size)
306
        {
307
            std::vector<hpx::future<T>> result;
1✔
308
            result.reserve(size);
1✔
309

310
            for (std::size_t i = 0; i != size; ++i)
4✔
311
            {
312
                result.push_back(extract_future_array<T>(i, f));
3✔
313
            }
3✔
314

315
            return result;
1✔
316
        }
1✔
317
    }    // namespace detail
318

319
    ///////////////////////////////////////////////////////////////////////////
320
    template <typename... Ts>
321
    HPX_FORCEINLINE hpx::tuple<hpx::future<Ts>...> split_future(
4✔
322
        hpx::future<hpx::tuple<Ts...>>&& f)
323
    {
324
        return detail::split_future_helper(
4✔
325
            HPX_MOVE(f), hpx::util::make_index_pack_t<sizeof...(Ts)>());
4✔
326
    }
327

328
    HPX_FORCEINLINE hpx::tuple<hpx::future<void>> split_future(
1✔
329
        hpx::future<hpx::tuple<>>&& f)
330
    {
331
        return hpx::make_tuple(hpx::future<void>(HPX_MOVE(f)));
1✔
332
    }
×
333

334
    template <typename... Ts>
335
    HPX_FORCEINLINE hpx::tuple<hpx::future<Ts>...> split_future(
3✔
336
        hpx::shared_future<hpx::tuple<Ts...>>&& f)
337
    {
338
        return detail::split_future_helper(
3✔
339
            HPX_MOVE(f), hpx::util::make_index_pack_t<sizeof...(Ts)>());
3✔
340
    }
341

342
    HPX_FORCEINLINE hpx::tuple<hpx::future<void>> split_future(
1✔
343
        hpx::shared_future<hpx::tuple<>>&& f)
344
    {
345
        return hpx::make_tuple(hpx::make_future<void>(HPX_MOVE(f)));
1✔
346
    }
×
347

348
    ///////////////////////////////////////////////////////////////////////////
349
#if defined(HPX_DATASTRUCTURES_HAVE_ADAPT_STD_TUPLE)
350
    template <typename... Ts>
351
    HPX_FORCEINLINE std::tuple<hpx::future<Ts>...> split_future(
1✔
352
        hpx::future<std::tuple<Ts...>>&& f)
353
    {
354
        return detail::split_future_helper(
1✔
355
            HPX_MOVE(f), hpx::util::make_index_pack_t<sizeof...(Ts)>());
1✔
356
    }
357

358
    HPX_FORCEINLINE std::tuple<hpx::future<void>> split_future(
359
        hpx::future<std::tuple<>>&& f)
360
    {
361
        return std::make_tuple(hpx::future<void>(HPX_MOVE(f)));
362
    }
363

364
    template <typename... Ts>
365
    HPX_FORCEINLINE std::tuple<hpx::future<Ts>...> split_future(
366
        hpx::shared_future<std::tuple<Ts...>>&& f)
367
    {
368
        return detail::split_future_helper(
369
            HPX_MOVE(f), hpx::util::make_index_pack_t<sizeof...(Ts)>());
370
    }
371

372
    HPX_FORCEINLINE std::tuple<hpx::future<void>> split_future(
373
        hpx::shared_future<std::tuple<>>&& f)
374
    {
375
        return std::make_tuple(hpx::make_future<void>(HPX_MOVE(f)));
376
    }
377
#endif
378

379
    ///////////////////////////////////////////////////////////////////////////
380
    template <typename T1, typename T2>
381
    HPX_FORCEINLINE std::pair<hpx::future<T1>, hpx::future<T2>> split_future(
2✔
382
        hpx::future<std::pair<T1, T2>>&& f)
383
    {
384
        return detail::split_future_helper(HPX_MOVE(f));
2✔
385
    }
386

387
    template <typename T1, typename T2>
388
    HPX_FORCEINLINE std::pair<hpx::future<T1>, hpx::future<T2>> split_future(
1✔
389
        hpx::shared_future<std::pair<T1, T2>>&& f)
390
    {
391
        return detail::split_future_helper(HPX_MOVE(f));
1✔
392
    }
393

394
    ///////////////////////////////////////////////////////////////////////////
395
    template <std::size_t N, typename T>
396
    HPX_FORCEINLINE std::array<hpx::future<T>, N> split_future(
2✔
397
        hpx::future<std::array<T, N>>&& f)
398
    {
399
        return detail::split_future_helper_array<N, T>(HPX_MOVE(f));
2✔
400
    }
401

402
    template <typename T>
403
    HPX_FORCEINLINE std::array<hpx::future<void>, 1> split_future(
2✔
404
        hpx::future<std::array<T, 0>>&& f)
405
    {
406
        std::array<hpx::future<void>, 1> result;
2✔
407
        result[0] = hpx::future<void>(HPX_MOVE(f));
2✔
408
        return result;
2✔
409
    }
2✔
410

411
    template <std::size_t N, typename T>
412
    HPX_FORCEINLINE std::array<hpx::future<T>, N> split_future(
413
        hpx::shared_future<std::array<T, N>>&& f)
414
    {
415
        return detail::split_future_helper_array<N, T>(HPX_MOVE(f));
416
    }
417

418
    template <typename T>
419
    HPX_FORCEINLINE std::array<hpx::future<void>, 1> split_future(
420
        hpx::shared_future<std::array<T, 0>>&& f)
421
    {
422
        std::array<hpx::future<void>, 1> result;
423
        result[0] = hpx::make_future<void>(HPX_MOVE(f));
424
        return result;
425
    }
426

427
    ///////////////////////////////////////////////////////////////////////////
428
    template <typename T>
429
    HPX_FORCEINLINE std::vector<hpx::future<T>> split_future(
1✔
430
        hpx::future<std::vector<T>>&& f, std::size_t size)
431
    {
432
        return detail::split_future_helper_vector<T>(HPX_MOVE(f), size);
1✔
433
    }
434

435
    template <typename T>
436
    HPX_FORCEINLINE std::vector<hpx::future<T>> split_future(
437
        hpx::shared_future<std::vector<T>>&& f, std::size_t size)
438
    {
439
        return detail::split_future_helper_vector<T>(HPX_MOVE(f), size);
440
    }
441
}    // namespace hpx
442

443
namespace hpx::lcos {
444

445
    template <typename F>
446
    HPX_DEPRECATED_V(1, 8,
447
        "hpx::lcos::split_future is deprecated. Use hpx::split_future instead.")
448
    decltype(auto) split_future(F&& future)
449
    {
450
        return hpx::split_future(HPX_FORWARD(F, future));
451
    }
452

453
    template <typename F>
454
    HPX_DEPRECATED_V(1, 8,
455
        "hpx::lcos::split_future is deprecated. Use hpx::split_future instead.")
456
    decltype(auto) split_future(F&& future, std::size_t size)
457
    {
458
        return hpx::split_future(HPX_FORWARD(F, future), size);
459
    }
460
}    // namespace hpx::lcos
461
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc