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

STEllAR-GROUP / hpx / #853

19 Dec 2022 01:01AM UTC coverage: 86.287% (+0.4%) from 85.912%
#853

push

StellarBot
Merge #6109

6109: Modernize serialization module r=hkaiser a=hkaiser

- flyby separate serialization of Boost types

working towards https://github.com/STEllAR-GROUP/hpx/issues/5497

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

53 of 53 new or added lines in 6 files covered. (100.0%)

173939 of 201582 relevant lines covered (86.29%)

1931657.12 hits per line

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

90.7
/libs/core/algorithms/include/hpx/parallel/util/low_level.hpp
1
//  Copyright (c) 2015-2017 Francisco Jose Tapia
2
//  Copyright (c) 2020 Hartmut Kaiser
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#pragma once
9

10
#include <hpx/config/forward.hpp>
11
#include <hpx/config/move.hpp>
12

13
#include <algorithm>
14
#include <functional>
15
#include <iterator>
16
#include <memory>
17
#include <type_traits>
18
#include <utility>
19
#include <vector>
20

21
namespace hpx { namespace parallel { namespace util {
22

23
    /// \brief create an object in the memory specified by ptr
24
    /// \tparam Value : typename of the object to create
25
    /// \tparam Args : parameters for the constructor
26
    /// \param [in] ptr : pointer to the memory where to create the object
27
    /// \param [in] args : arguments to the constructor
28
    template <typename Value, typename... Args>
29
    inline void construct_object(Value* ptr, Args&&... args)
1,160,359✔
30
    {
31
        (::new (static_cast<void*>(ptr)) Value(HPX_FORWARD(Args, args)...));
1,160,565✔
32
    }
1,160,565✔
33

34
    /// \brief destroy an object in the memory specified by ptr
35
    /// \tparam Value : typename of the object to create
36
    /// \param [in] ptr : pointer to the object to destroy
37
    //-----------------------------------------------------------------------------
38
    template <typename Value>
39
    inline void destroy_object(Value* ptr)
40
    {
41
        std::destroy_at(ptr);
42
    }
43

44
    /// Initialize a range of objects with the object val moving across them
45
    /// \param [in] r : range of elements not initialized
46
    /// \param [in] val : object used for the initialization
47
    /// \return range initialized
48
    template <typename Iter, typename Sent>
49
    inline void init(Iter first, Sent last,
1✔
50
        typename std::iterator_traits<Iter>::value_type& val)
51
    {
52
        if (first == last)
1✔
53
        {
54
            return;
×
55
        }
56

57
        construct_object(&(*first), HPX_MOVE(val));
1✔
58

59
        Iter it1 = first, it2 = first + 1;
1✔
60
        while (it2 != last)
100✔
61
        {
62
            // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
63
            construct_object(&(*(it2++)), HPX_MOVE(*(it1++)));
99✔
64
        }
65

66
        val = HPX_MOVE(*(last - 1));
1✔
67
    }
1✔
68

69
    /// \brief create an object in the memory specified by ptr
70
    /// \tparam Value : typename of the object to create
71
    /// \tparam Args : parameters for the constructor
72
    /// \param [in] ptr : pointer to the memory where to create the object
73
    /// \param [in] args : arguments to the constructor
74
    template <typename Value, typename... Args>
75
    inline void construct(Value* ptr, Args&&... args)
60,032✔
76
    {
77
        (::new (static_cast<void*>(ptr)) Value(HPX_FORWARD(Args, args)...));
60,028✔
78
    }
60,028✔
79

80
    /// \brief Move objects
81
    /// \tparam Iter : iterator to the elements
82
    /// \tparam Value : typename of the object to create
83
    /// \param [in] itdest : iterator to the final place of the objects
84
    /// \param [in] R : range to move
85
    template <typename Iter1, typename Sent1, typename Iter2>
86
    inline Iter2 init_move(Iter2 it_dest, Iter1 first, Sent1 last)
268,575✔
87
    {
88
        while (first != last)
7,764,130✔
89
        {
90
            // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
91
            *(it_dest++) = HPX_MOVE(*(first++));
7,495,565✔
92
        }
93
        return it_dest;
268,546✔
94
    }
×
95

96
    /// \brief Move objects to uninitialized memory
97
    /// \tparam Iter : iterator to the elements
98
    /// \tparam Value : typename of the object to construct
99
    /// \param [in] ptr : pointer to the memory where to create the object
100
    /// \param [in] R : range to move
101
    template <typename Iter, typename Sent,
102
        typename Value = typename std::iterator_traits<Iter>::value_type>
103
    inline Value* uninit_move(Value* ptr, Iter first, Sent last)
30,958✔
104
    {
105
        using value_type = typename std::iterator_traits<Iter>::value_type;
106

107
        static_assert(
108
            std::is_same<Value, value_type>::value, "Incompatible iterators\n");
109

110
        while (first != last)
2,780,390✔
111
        {
112
            // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
113
            ::new (static_cast<void*>(ptr++)) Value(HPX_MOVE(*(first++)));
2,750,245✔
114
        }
115

116
        return ptr;
30,933✔
117
    }
×
118

119
    /// \brief Move objects to uninitialized memory
120
    /// \tparam Iter : iterator to the elements
121
    /// \tparam Value : typename of the object to construct
122
    /// \param [in] ptr : pointer to the memory where to construct the object
123
    /// \param [in] R : range to move
124
    template <typename Iter, typename Sent>
125
    inline void destroy(Iter first, Sent last)
319✔
126
    {
127
        while (first != last)
4,429,886✔
128
        {
129
            std::destroy_at(&(*(first++)));
4,429,567✔
130
        }
131
    }
319✔
132

133
    /// \brief Merge two contiguous buffers pointed by buf1 and buf2 , and put
134
    ///        in the buffer pointed by buf_out
135
    /// \param [in] buf1 : iterator to the first element in the first buffer
136
    /// \param [in] end_buf1 : final iterator of first buffer
137
    /// \param [in] buf2 : iterator to the first iterator to the second buffer
138
    /// \param [in] end_buf2 : final iterator of the second buffer
139
    /// \param [in] buf_out : buffer where move the elements merged
140
    /// \param [in] comp : comparison object
141
    template <typename Iter1, typename Sent1, typename Iter2, typename Compare>
142
    inline Iter2 full_merge(Iter1 buf1, Sent1 end_buf1, Iter1 buf2,
268,314✔
143
        Sent1 end_buf2, Iter2 buf_out, Compare comp)
144
    {
145
        using value1_t = typename std::iterator_traits<Iter1>::value_type;
146
        using value2_t = typename std::iterator_traits<Iter2>::value_type;
147

148
        static_assert(std::is_same<value1_t, value2_t>::value,
149
            "Incompatible iterators\n");
150

151
        while ((buf1 != end_buf1) && (buf2 != end_buf2))
52,245,265✔
152
        {
153
            *(buf_out++) = (!comp(*buf2, *buf1)) ?
50,272,420✔
154
                // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
155
                HPX_MOVE(*(buf1++)) :
23,793,599✔
156
                // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
157
                HPX_MOVE(*(buf2++));
28,183,352✔
158
        }
159
        return (buf1 == end_buf1) ? init_move(buf_out, buf2, end_buf2) :
268,293✔
160
                                    init_move(buf_out, buf1, end_buf1);
151,911✔
161
    }
×
162

163
    /// \brief Merge two contiguous buffers pointed by first1 and first2 , and put
164
    ///        in the uninitialized buffer pointed by it_out
165
    /// \param [in] first1 : iterator to the first element in the first buffer
166
    /// \param [in] last : last iterator of the first buffer
167
    /// \param [in] first2 : iterator to the first element to the second buffer
168
    /// \param [in] last22 : final iterator of the second buffer
169
    /// \param [in] it_out : uninitialized buffer where move the elements merged
170
    /// \param [in] comp : comparison object
171
    template <typename Iter, typename Sent, typename Value, typename Compare>
172
    inline Value* uninit_full_merge(Iter first1, Sent last1, Iter first2,
30,601✔
173
        Sent last2, Value* it_out, Compare comp)
174
    {
175
        using type1 = typename std::iterator_traits<Iter>::value_type;
176

177
        static_assert(
178
            std::is_same<Value, type1>::value, "Incompatible iterators\n");
179

180
        while (first1 != last1 && first2 != last2)
91,662✔
181
        {
182
            construct((it_out++),
120,713✔
183
                (!comp(*first2, *first1)) ?
59,652✔
184
                    // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
185
                    HPX_MOVE(*(first1++)) :
30,505✔
186
                    // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
187
                    HPX_MOVE(*(first2++)));
30,556✔
188
        };
189
        return (first1 == last1) ? uninit_move(it_out, first2, last2) :
30,550✔
190
                                   uninit_move(it_out, first1, last1);
15,410✔
191
    }
×
192

193
    /// \brief : Merge two buffers. The first buffer is in a separate memory.
194
    ///          The second buffer have a empty space before buf2 of the same size
195
    ///          than the (end_buf1 - buf1)
196
    /// \param [in] buf1 : iterator to the first element of the first buffer
197
    /// \param [in] end_buf1 : iterator to the last element of the first buffer
198
    /// \param [in] buf2 : iterator to the first element of the second buffer
199
    /// \param [in] end_buf2 : iterator to the last element of the second buffer
200
    /// \param [in] buf_out : iterator to the first element to the buffer where put
201
    ///                       the result
202
    /// \param [in] comp : object for Compare two elements of the type pointed
203
    ///                    by the Iter1 and Iter2
204
    /// \remarks The elements pointed by Iter1 and Iter2 must be the same
205
    template <typename Iter1, typename Sent1, typename Iter2, typename Sent2,
206
        typename Compare>
207
    inline Iter2 half_merge(Iter1 buf1, Sent1 end_buf1, Iter2 buf2,
355✔
208
        Sent2 end_buf2, Iter2 buf_out, Compare comp)
209
    {
210
        using value1_t = typename std::iterator_traits<Iter1>::value_type;
211
        using value2_t = typename std::iterator_traits<Iter2>::value_type;
212

213
        static_assert(std::is_same<value1_t, value2_t>::value,
214
            "Incompatible iterators\n");
215

216
        while ((buf1 != end_buf1) && (buf2 != end_buf2))
6,498,879✔
217
        {
218
            *(buf_out++) = (!comp(*buf2, *buf1)) ?
6,263,284✔
219
                // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
220
                HPX_MOVE(*(buf1++)) :
2,996,982✔
221
                // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
222
                HPX_MOVE(*(buf2++));
3,501,542✔
223
        }
224
        return (buf2 == end_buf2) ? init_move(buf_out, buf1, end_buf1) :
355✔
225
                                    end_buf2;
174✔
226
    }
×
227

228
    /// Merge two non contiguous buffers, placing the results in the buffers
229
    ///          for to do this use an auxiliary buffer pointed by aux
230
    /// \param [in] src1 : iterator to the first element of the first buffer
231
    /// \param [in] end_src1 : last iterator  of the first buffer
232
    /// \param [in] src2 : iterator to the first element of the second buffer
233
    /// \param [in] end_src2 : last iterator  of the second buffer
234
    /// \param [in] aux  : iterator to the first element of the auxiliary buffer
235
    /// \param [in] comp : object for to Compare elements
236
    /// \exception
237
    /// \return true : not changes done
238
    ///         false : changes in the buffers
239
    /// \remarks
240
    template <typename Iter1, typename Sent1, typename Iter2, typename Sent2,
241
        typename Iter3, typename Compare>
242
    bool in_place_merge_uncontiguous(Iter1 src1, Sent1 end_src1, Iter2 src2,
11✔
243
        Sent2 end_src2, Iter3 aux, Compare comp)
244
    {
245
        using type1 = typename std::iterator_traits<Iter1>::value_type;
246
        using type2 = typename std::iterator_traits<Iter2>::value_type;
247
        using type3 = typename std::iterator_traits<Iter3>::value_type;
248

249
        static_assert(
250
            std::is_same<type1, type2>::value, "Incompatible iterators\n");
251
        static_assert(
252
            std::is_same<type3, type2>::value, "Incompatible iterators\n");
253

254
        if (src1 == end_src1 || src2 == end_src2 ||
11✔
255
            !comp(*src2, *(end_src1 - 1)))
9✔
256
        {
257
            return true;
4✔
258
        }
259

260
        while (src1 != end_src1 && !comp(*src2, *src1))
63✔
261
        {
262
            ++src1;
56✔
263
        }
264

265
        Iter3 const end_aux = aux + (end_src1 - src1);
7✔
266
        Iter2 src2_first = src2;
7✔
267
        init_move(aux, src1, end_src1);
7✔
268

269
        while ((src1 != end_src1) && (src2 != end_src2))
199✔
270
        {
271
            *(src1++) = std::move((!comp(*src2, *aux)) ? *(aux++) : *(src2++));
192✔
272
        }
273

274
        if (src2 == end_src2)
7✔
275
        {
276
            while (src1 != end_src1)
3✔
277
            {
278
                // NOLINTNEXTLINE(bugprone-macro-repeated-side-effects)
279
                *(src1++) = HPX_MOVE(*(aux++));
×
280
            }
281
            init_move(src2_first, aux, end_aux);
3✔
282
        }
3✔
283
        else
284
        {
285
            half_merge(aux, end_aux, src2, end_src2, src2_first, comp);
4✔
286
        }
287
        return false;
7✔
288
    }
11✔
289

290
    /// \brief : merge two contiguous buffers,using an auxiliary buffer pointed
291
    ///          by buf
292
    ///
293
    /// \param [in] src1: iterator to the first position of the first buffer
294
    /// \param [in] src2: final iterator of the first buffer and first iterator
295
    ///                   of the second buffer
296
    /// \param [in] end_src2 : final iterator of the second buffer
297
    /// \param [in] buf  : iterator to buffer used as auxiliary memory
298
    /// \param [in] comp : object for to Compare elements
299
    /// \exception
300
    /// \return true : not changes done
301
    ///         false : changes in the buffers
302
    /// \remarks
303
    template <typename Iter1, typename Sent1, typename Iter2, typename Compare>
304
    inline bool in_place_merge(
10✔
305
        Iter1 src1, Iter1 src2, Sent1 end_src2, Iter2 buf, Compare comp)
306
    {
307
        using type1 = typename std::iterator_traits<Iter1>::value_type;
308
        using type2 = typename std::iterator_traits<Iter2>::value_type;
309

310
        static_assert(
311
            std::is_same<type1, type2>::value, "Incompatible iterators\n");
312

313
        if (src1 == src2 || src2 == end_src2 || !comp(*src2, *(src2 - 1)))
10✔
314
        {
315
            return true;
4✔
316
        }
317

318
        Iter1 end_src1 = src2;
6✔
319
        while (src1 != end_src1 && !comp(*src2, *src1))
59✔
320
        {
321
            ++src1;
53✔
322
        }
323

324
        if (src1 == end_src1)
6✔
325
        {
326
            return false;
×
327
        }
328

329
        size_t nx = end_src1 - src1;
6✔
330
        init_move(buf, src1, end_src1);
6✔
331
        half_merge(buf, buf + nx, src2, end_src2, src1, comp);
6✔
332
        return false;
6✔
333
    }
10✔
334
}}}    // namespace hpx::parallel::util
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