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

STEllAR-GROUP / hpx / #867

15 Jan 2023 08:00PM UTC coverage: 86.487% (+0.5%) from 85.951%
#867

push

StellarBot
Merge #6135

6135: Fixing warnings reported by MSVC analysis r=hkaiser a=hkaiser

- adding MSVC specific #pragma's to suppress the benign warnings


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

120 of 120 new or added lines in 33 files covered. (100.0%)

174599 of 201880 relevant lines covered (86.49%)

1945607.64 hits per line

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

87.82
/libs/core/lcos_local/src/composable_guard.cpp
1
//  (C) Copyright 2013-2015 Steven R. Brandt
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
#include <hpx/config.hpp>
8
#include <hpx/assert.hpp>
9
#include <hpx/functional/bind_front.hpp>
10
#include <hpx/functional/function.hpp>
11

12
#include <hpx/lcos_local/composable_guard.hpp>
13

14
#include <algorithm>
15
#include <atomic>
16
#include <cstddef>
17
#include <memory>
18
#include <utility>
19
#include <vector>
20

21
namespace hpx::lcos::local {
22

23
    static void run_composable(detail::guard_task* task);
24

25
    static constexpr void nothing() noexcept {}
×
26

27
    namespace detail {
28

29
        // A link in the list of tasks attached to a guard
30
        struct guard_task : detail::debug_object
26,510✔
31
        {
32
            std::atomic<guard_task*> next;
33
            detail::guard_function run;
34
            bool const single_guard;
35

36
            guard_task()
14,506✔
37
              : next(nullptr)
14,506✔
38
              , run(nothing)
14,506✔
39
              , single_guard(true)
14,506✔
40
            {
14,506✔
41
            }
14,506✔
42

43
            explicit guard_task(bool sg)
12,004✔
44
              : next(nullptr)
12,004✔
45
              , run(nothing)
12,004✔
46
              , single_guard(sg)
12,004✔
47
            {
12,004✔
48
            }
12,004✔
49
        };
50

51
        void free(guard_task* task)
24,004✔
52
        {
53
            if (task == nullptr)
24,004✔
54
                return;
×
55
            task->check_();
24,004✔
56
            delete task;
24,004✔
57
        }
24,004✔
58
    }    // namespace detail
59

60
    void guard_set::sort()
6,002✔
61
    {
62
        if (!sorted)
6,002✔
63
        {
64
            std::sort(guards.begin(), guards.end());
2✔
65
            (*guards.begin())->check_();
2✔
66
            sorted = true;
2✔
67
        }
2✔
68
    }
6,002✔
69

70
    struct stage_data : public detail::debug_object
71
    {
72
        guard_set gs;
73
        detail::guard_function task;
74
        std::size_t n;
75
        detail::guard_task** stages;
76

77
        stage_data(detail::guard_function task_,
6,002✔
78
            std::vector<std::shared_ptr<guard>>& guards)
79
          : gs()
6,002✔
80
          , task(HPX_MOVE(task_))
6,002✔
81
          , n(guards.size())
6,002✔
82
          , stages(new detail::guard_task*[n])
6,002✔
83
        {
6,002✔
84
            for (std::size_t i = 0; i < n; i++)
18,006✔
85
            {
86
                stages[i] = new detail::guard_task(false);
12,004✔
87
            }
12,004✔
88
        }
6,002✔
89

90
        ~stage_data()
6,002✔
91
        {
92
            if (stages == nullptr)
6,002✔
93
                abort();
×
94
            HPX_ASSERT(n == gs.size());
6,002✔
95
            delete[] stages;
6,002✔
96
            stages = nullptr;
6,002✔
97
        }
6,002✔
98
    };
99

100
    static void run_guarded(guard& g, detail::guard_task* task)
24,004✔
101
    {
102
        HPX_ASSERT(task != nullptr);
24,004✔
103
        task->check_();
24,004✔
104
        detail::guard_task* prev = g.task.exchange(task);
24,004✔
105
        if (prev != nullptr)
24,004✔
106
        {
107
            prev->check_();
24,000✔
108
            detail::guard_task* zero = nullptr;
24,000✔
109
            if (!prev->next.compare_exchange_strong(zero, task))
24,000✔
110
            {
111
                run_composable(task);
24,000✔
112
                free(prev);
24,000✔
113
            }
24,000✔
114
        }
24,000✔
115
        else
116
        {
117
            run_composable(task);
4✔
118
        }
119
    }
24,004✔
120

121
    struct stage_task_cleanup
122
    {
123
        stage_data* sd;
124
        std::size_t n;
125
        stage_task_cleanup(stage_data* sd_, std::size_t n_) noexcept
6,002✔
126
          : sd(sd_)
6,002✔
127
          , n(n_)
6,002✔
128
        {
129
        }
6,002✔
130

131
        ~stage_task_cleanup()
6,002✔
132
        {
133
            detail::guard_task* zero = nullptr;
6,002✔
134
            // The tasks on the other guards had single_task marked,
135
            // so they haven't had their next field set yet. Setting
136
            // the next field is necessary if they are going to
137
            // continue processing.
138
            for (std::size_t k = 0; k < n; k++)
18,006✔
139
            {
140
                detail::guard_task* lt = sd->stages[k];
12,004✔
141
                lt->check_();
12,004✔
142
                HPX_ASSERT(!lt->single_guard);
12,004✔
143
                zero = nullptr;
12,004✔
144
                if (!lt->next.compare_exchange_strong(zero, lt))
12,004✔
145
                {
146
                    HPX_ASSERT(zero != lt);
×
147
                    run_composable(zero);
×
148
                    free(lt);
×
149
                }
×
150
            }
12,004✔
151
            delete sd;
6,002✔
152
        }
6,002✔
153
    };
154

155
    static void stage_task(stage_data* sd, std::size_t i, std::size_t n)
12,004✔
156
    {
157
        // if this is the last task in the set...
158
        if (i + 1 == n)
12,004✔
159
        {
160
            stage_task_cleanup stc(sd, n);
6,002✔
161
            sd->task();
6,002✔
162
        }
6,002✔
163
        else
164
        {
165
            std::size_t k = i + 1;
6,002✔
166
            detail::guard_task* stage = sd->stages[k];
6,002✔
167
            stage->run = hpx::bind_front(stage_task, sd, k, n);
6,002✔
168
            HPX_ASSERT(!stage->single_guard);
6,002✔
169
            run_guarded(*sd->gs.get(k), stage);
6,002✔
170
        }
171
    }
12,004✔
172

173
    void run_guarded(guard_set& guards, detail::guard_function task)
6,002✔
174
    {
175
        std::size_t n = guards.guards.size();
6,002✔
176
        if (n == 0)
6,002✔
177
        {
178
            task();
×
179
            return;
×
180
        }
181
        else if (n == 1)
6,002✔
182
        {
183
            run_guarded(*guards.guards[0], HPX_MOVE(task));
×
184
            guards.check_();
×
185
            return;
×
186
        }
187
        guards.sort();
6,002✔
188
        stage_data* sd = new stage_data(HPX_MOVE(task), guards.guards);
6,002✔
189
        int k = 0;
6,002✔
190
        sd->stages[k]->run = hpx::bind_front(stage_task, sd, k, n);
6,002✔
191
        sd->gs = guards;
6,002✔
192
        detail::guard_task* stage = sd->stages[k];    //-V108
6,002✔
193
        run_guarded(*sd->gs.get(k), stage);           //-V106
6,002✔
194
    }
6,002✔
195

196
    void run_guarded(guard& guard, detail::guard_function task)
12,000✔
197
    {
198
        detail::guard_task* tptr = new detail::guard_task();
12,000✔
199
        tptr->run = HPX_MOVE(task);
12,000✔
200
        run_guarded(guard, tptr);
12,000✔
201
    }
12,000✔
202

203
    // This class exists so that a destructor is used to perform cleanup. By
204
    // using a destructor we ensure the code works even if exceptions are
205
    // thrown.
206
    struct run_composable_cleanup
207
    {
208
        detail::guard_task* task;
209
        explicit run_composable_cleanup(detail::guard_task* task_) noexcept
12,000✔
210
          : task(task_)
12,000✔
211
        {
212
        }
12,000✔
213
        ~run_composable_cleanup()
12,000✔
214
        {
215
            detail::guard_task* zero = nullptr;
12,000✔
216

217
            // If single_guard is false, then this is one of the setup tasks for
218
            // a multi-guarded task. By not setting the next field, we halt
219
            // processing on items queued to this guard.
220
            if (task != nullptr)
12,000✔
221
            {
222
                task->check_();
12,000✔
223
                if (!task->next.compare_exchange_strong(zero, task))
12,000✔
224
                {
225
                    HPX_ASSERT(zero != nullptr);
×
226
                    run_composable(zero);
×
227
                    free(task);
×
228
                }
×
229
            }
12,000✔
230
        }
12,000✔
231
    };
232

233
    namespace detail {
234

235
        struct empty_helper
236
        {
237
            static guard_task*& get_empty_guard_task()
1,253✔
238
            {
239
                static guard_task* empty = new guard_task;
1,253✔
240
                return empty;
1,253✔
241
            }
×
242

243
            empty_helper() = default;
244
            ~empty_helper()
1,253✔
245
            {
246
                auto& empty = get_empty_guard_task();
1,253✔
247
                delete empty;
1,253✔
248
                empty = nullptr;
1,253✔
249
            }
1,253✔
250
        };
251

252
        empty_helper empty_helper_{};
1,253✔
253
    }    // namespace detail
254

255
    using hpx::lcos::local::detail::guard_task;
256
    static guard_task empty;
1,253✔
257

258
    static void run_composable(detail::guard_task* task)
24,004✔
259
    {
260
        if (task == &empty)
24,004✔
261
            return;
×
262
        if (task != nullptr)
24,004✔
263
        {
264
            task->check_();
24,004✔
265
            if (task->single_guard)
24,004✔
266
            {
267
                run_composable_cleanup rcc(task);
12,000✔
268
                task->run();
12,000✔
269
            }
12,000✔
270
            else
271
            {
272
                task->run();
12,004✔
273
                // Note that by this point in the execution the task data
274
                // structure has probably been deleted.
275
            }
276
        }
24,004✔
277
    }
24,004✔
278

279
    guard::~guard()
4✔
280
    {
281
        guard_task* zero = nullptr;
4✔
282
        guard_task* current = task.load();
4✔
283
        if (current == nullptr)
4✔
284
            return;
×
285
        if (!current->next.compare_exchange_strong(zero, &empty))
4✔
286
        {
287
            free(zero);
4✔
288
        }
4✔
289
    }
4✔
290
}    // namespace hpx::lcos::local
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