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

STEllAR-GROUP / hpx / #845

05 Dec 2022 08:25PM UTC coverage: 85.664% (-0.1%) from 85.8%
#845

push

StellarBot
Merge #6091

6091: Replace artificial sequencing with fold expressions r=hkaiser a=hkaiser

- flyby: fix left-over problems from namespace change

working towards resolving #5497

Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

99 of 99 new or added lines in 15 files covered. (100.0%)

171125 of 199764 relevant lines covered (85.66%)

1865254.07 hits per line

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

79.05
/libs/full/segmented_algorithms/include/hpx/parallel/segmented_algorithms/for_each.hpp
1
//  Copyright (c) 2007-2021 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
#pragma once
8

9
#include <hpx/config.hpp>
10
#include <hpx/algorithms/traits/segmented_iterator_traits.hpp>
11

12
#include <hpx/executors/execution_policy.hpp>
13
#include <hpx/parallel/algorithms/detail/dispatch.hpp>
14
#include <hpx/parallel/algorithms/for_each.hpp>
15
#include <hpx/parallel/segmented_algorithms/detail/dispatch.hpp>
16
#include <hpx/parallel/util/detail/algorithm_result.hpp>
17
#include <hpx/parallel/util/detail/handle_remote_exceptions.hpp>
18

19
#include <algorithm>
20
#include <cstddef>
21
#include <exception>
22
#include <iterator>
23
#include <list>
24
#include <type_traits>
25
#include <utility>
26
#include <vector>
27

28
namespace hpx { namespace parallel { inline namespace v1 {
29

30
    ///////////////////////////////////////////////////////////////////////////
31
    // segmented_for_each
32
    namespace detail {
33
        ///////////////////////////////////////////////////////////////////////
34
        /// \cond NOINTERNAL
35

36
        // sequential remote implementation
37
        template <typename Algo, typename ExPolicy, typename SegIter,
38
            typename F, typename Proj>
39
        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
40
        segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first,
10✔
41
            SegIter last, F&& f, Proj&& proj, std::true_type)
42
        {
43
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
44
            typedef typename traits::segment_iterator segment_iterator;
45
            typedef typename traits::local_iterator local_iterator_type;
46
            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;
47

48
            segment_iterator sit = traits::segment(first);
10✔
49
            segment_iterator send = traits::segment(last);
10✔
50

51
            if (sit == send)
10✔
52
            {
53
                // all elements are on the same partition
54
                local_iterator_type beg = traits::local(first);
×
55
                local_iterator_type end = traits::local(last);
×
56
                if (beg != end)
×
57
                {
58
                    local_iterator_type out = dispatch(traits::get_id(sit),
×
59
                        algo, policy, std::true_type(), beg, end, f, proj);
×
60
                    last = traits::compose(send, out);
×
61
                }
×
62
            }
×
63
            else
64
            {
65
                // handle the remaining part of the first partition
66
                local_iterator_type beg = traits::local(first);
10✔
67
                local_iterator_type end = traits::end(sit);
10✔
68
                local_iterator_type out = traits::local(last);
10✔
69

70
                if (beg != end)
10✔
71
                {
72
                    out = dispatch(traits::get_id(sit), algo, policy,
10✔
73
                        std::true_type(), beg, end, f, proj);
10✔
74
                }
10✔
75

76
                // handle all of the full partitions
77
                for (++sit; sit != send; ++sit)
20✔
78
                {
79
                    beg = traits::begin(sit);
10✔
80
                    end = traits::end(sit);
10✔
81
                    out = traits::begin(send);
10✔
82

83
                    if (beg != end)
10✔
84
                    {
85
                        out = dispatch(traits::get_id(sit), algo, policy,
10✔
86
                            std::true_type(), beg, end, f, proj);
10✔
87
                    }
10✔
88
                }
10✔
89

90
                // handle the beginning of the last partition
91
                beg = traits::begin(sit);
10✔
92
                end = traits::local(last);
10✔
93
                if (beg != end)
10✔
94
                {
95
                    out = dispatch(traits::get_id(sit), algo, policy,
×
96
                        std::true_type(), beg, end, f, proj);
×
97
                }
×
98

99
                last = traits::compose(send, out);
10✔
100
            }
10✔
101

102
            return result::get(HPX_MOVE(last));
10✔
103
        }
×
104

105
        // parallel remote implementation
106
        template <typename Algo, typename ExPolicy, typename SegIter,
107
            typename F, typename Proj>
108
        static typename util::detail::algorithm_result<ExPolicy, SegIter>::type
109
        segmented_for_each(Algo&& algo, ExPolicy const& policy, SegIter first,
32✔
110
            SegIter last, F&& f, Proj&& proj, std::false_type)
111
        {
112
            typedef hpx::traits::segmented_iterator_traits<SegIter> traits;
113
            typedef typename traits::segment_iterator segment_iterator;
114
            typedef typename traits::local_iterator local_iterator_type;
115
            typedef util::detail::algorithm_result<ExPolicy, SegIter> result;
116

117
            typedef std::integral_constant<bool,
118
                !hpx::traits::is_forward_iterator<SegIter>::value>
119
                forced_seq;
120

121
            segment_iterator sit = traits::segment(first);
32✔
122
            segment_iterator send = traits::segment(last);
32✔
123

124
            std::vector<future<local_iterator_type>> segments;
32✔
125
            segments.reserve(std::distance(sit, send));
32✔
126

127
            if (sit == send)
32✔
128
            {
129
                // all elements are on the same partition
130
                local_iterator_type beg = traits::local(first);
×
131
                local_iterator_type end = traits::local(last);
×
132
                if (beg != end)
×
133
                {
134
                    segments.push_back(dispatch_async(traits::get_id(sit), algo,
×
135
                        policy, forced_seq(), beg, end, f, proj));
×
136
                }
×
137
            }
×
138
            else
139
            {
140
                // handle the remaining part of the first partition
141
                local_iterator_type beg = traits::local(first);
32✔
142
                local_iterator_type end = traits::end(sit);
32✔
143
                if (beg != end)
32✔
144
                {
145
                    segments.push_back(dispatch_async(traits::get_id(sit), algo,
32✔
146
                        policy, forced_seq(), beg, end, f, proj));
32✔
147
                }
32✔
148

149
                // handle all of the full partitions
150
                for (++sit; sit != send; ++sit)
40✔
151
                {
152
                    beg = traits::begin(sit);
8✔
153
                    end = traits::end(sit);
8✔
154
                    if (beg != end)
8✔
155
                    {
156
                        segments.push_back(dispatch_async(traits::get_id(sit),
8✔
157
                            algo, policy, forced_seq(), beg, end, f, proj));
8✔
158
                    }
8✔
159
                }
8✔
160

161
                // handle the beginning of the last partition
162
                beg = traits::begin(sit);
32✔
163
                end = traits::local(last);
32✔
164
                if (beg != end)
32✔
165
                {
166
                    segments.push_back(dispatch_async(traits::get_id(sit), algo,
×
167
                        policy, forced_seq(), beg, end, f, proj));
×
168
                }
×
169
            }
32✔
170

171
            return result::get(dataflow(
32✔
172
                [=](std::vector<hpx::future<local_iterator_type>>&& r)
64✔
173
                    -> SegIter {
174
                    // handle any remote exceptions, will throw on error
175
                    std::list<std::exception_ptr> errors;
32✔
176
                    parallel::util::detail::handle_remote_exceptions<
32✔
177
                        ExPolicy>::call(r, errors);
32✔
178
                    return traits::compose(send, r.back().get());
32✔
179
                },
32✔
180
                HPX_MOVE(segments)));
181
        }
32✔
182
        /// \endcond
183
    }    // namespace detail
184
}}}      // namespace hpx::parallel::v1
185

186
// The segmented iterators we support all live in namespace hpx::segmented
187
namespace hpx { namespace segmented {
188

189
    // clang-format off
190
    template <typename InIter,
191
        typename F,
192
        HPX_CONCEPT_REQUIRES_(
193
            hpx::traits::is_iterator<InIter>::value &&
194
            hpx::traits::is_segmented_iterator<InIter>::value
195
        )>
196
    // clang-format on
197
    InIter tag_invoke(hpx::for_each_t, InIter first, InIter last, F&& f)
4✔
198
    {
199
        static_assert((hpx::traits::is_forward_iterator<InIter>::value),
200
            "Requires at least input iterator.");
201

202
        using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>;
203

204
        if (first == last)
4✔
205
        {
206
            return first;
2✔
207
        }
208

209
        return hpx::parallel::v1::detail::segmented_for_each(
2✔
210
            hpx::parallel::v1::detail::for_each<
2✔
211
                typename iterator_traits::local_iterator>(),
212
            hpx::execution::seq, first, last, HPX_FORWARD(F, f),
2✔
213
            hpx::parallel::util::projection_identity(), std::true_type());
214
    }
4✔
215

216
    // clang-format off
217
    template <typename ExPolicy, typename SegIter,
218
        typename F,
219
        HPX_CONCEPT_REQUIRES_(
220
            hpx::is_execution_policy<ExPolicy>::value &&
221
            hpx::traits::is_iterator<SegIter>::value &&
222
            hpx::traits::is_segmented_iterator<SegIter>::value
223
        )>
224
    // clang-format on
225
    typename hpx::parallel::util::detail::algorithm_result<ExPolicy,
226
        SegIter>::type
227
    tag_invoke(
16✔
228
        hpx::for_each_t, ExPolicy&& policy, SegIter first, SegIter last, F&& f)
229
    {
230
        static_assert((hpx::traits::is_forward_iterator<SegIter>::value),
231
            "Requires at least forward iterator.");
232

233
        using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>;
234

235
        if (first == last)
16✔
236
        {
237
            using result =
238
                hpx::parallel::util::detail::algorithm_result<ExPolicy,
239
                    SegIter>;
240
            return result::get(HPX_MOVE(first));
8✔
241
        }
242

243
        using iterator_traits = hpx::traits::segmented_iterator_traits<SegIter>;
244

245
        return segmented_for_each(
8✔
246
            hpx::parallel::v1::detail::for_each<
8✔
247
                typename iterator_traits::local_iterator>(),
248
            HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f),
8✔
249
            hpx::parallel::util::projection_identity(), is_seq());
8✔
250
    }
16✔
251

252
    // clang-format off
253
    template <typename InIter, typename Size,
254
        typename F,
255
        HPX_CONCEPT_REQUIRES_(
256
            hpx::traits::is_iterator<InIter>::value &&
257
            hpx::traits::is_segmented_iterator<InIter>::value
258
        )>
259
    // clang-format on
260
    InIter tag_invoke(hpx::for_each_n_t, InIter first, Size count, F&& f)
261
    {
262
        static_assert((hpx::traits::is_input_iterator<InIter>::value),
263
            "Requires at least input iterator.");
264

265
        using iterator_traits = hpx::traits::segmented_iterator_traits<InIter>;
266

267
        if (hpx::parallel::v1::detail::is_negative(count) || count == 0)
268
        {
269
            return first;
270
        }
271

272
        auto last = first;
273
        hpx::parallel::v1::detail::advance(last, std::size_t(count));
274
        return hpx::parallel::v1::detail::segmented_for_each(
275
            hpx::parallel::v1::detail::for_each<
276
                typename iterator_traits::local_iterator>(),
277
            hpx::execution::seq, first, last, HPX_FORWARD(F, f),
278
            hpx::parallel::util::projection_identity(), std::true_type());
279
    }
280

281
    // clang-format off
282
    template <typename ExPolicy, typename SegIter, typename Size,
283
        typename F,
284
        HPX_CONCEPT_REQUIRES_(
285
            hpx::is_execution_policy<ExPolicy>::value &&
286
            hpx::traits::is_iterator<SegIter>::value &&
287
            hpx::traits::is_segmented_iterator<SegIter>::value
288
        )>
289
    // clang-format on
290
    typename hpx::parallel::util::detail::algorithm_result<ExPolicy,
291
        SegIter>::type
292
    tag_invoke(
24✔
293
        hpx::for_each_n_t, ExPolicy&& policy, SegIter first, Size count, F&& f)
294
    {
295
        static_assert((hpx::traits::is_forward_iterator<SegIter>::value),
296
            "Requires at least input iterator.");
297

298
        using is_seq = hpx::is_sequenced_execution_policy<ExPolicy>;
299

300
        if (hpx::parallel::v1::detail::is_negative(count) || count == 0)
24✔
301
        {
302
            using result =
303
                hpx::parallel::util::detail::algorithm_result<ExPolicy,
304
                    SegIter>;
305
            return result::get(HPX_MOVE(first));
16✔
306
        }
307

308
        using iterator_traits = hpx::traits::segmented_iterator_traits<SegIter>;
309

310
        auto last = first;
8✔
311
        hpx::parallel::v1::detail::advance(last, std::size_t(count));
8✔
312
        return segmented_for_each(
8✔
313
            hpx::parallel::v1::detail::for_each<
8✔
314
                typename iterator_traits::local_iterator>(),
315
            HPX_FORWARD(ExPolicy, policy), first, last, HPX_FORWARD(F, f),
8✔
316
            hpx::parallel::util::projection_identity(), is_seq());
8✔
317
    }
24✔
318
}}    // namespace hpx::segmented
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

© 2026 Coveralls, Inc