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

STEllAR-GROUP / hpx / #856

28 Dec 2022 02:00AM UTC coverage: 86.602% (+0.05%) from 86.55%
#856

push

StellarBot
Merge #6119

6119: Update CMakeLists.txt r=hkaiser a=khuck

updating the default APEX version


Co-authored-by: Kevin Huck <khuck@cs.uoregon.edu>

174566 of 201573 relevant lines covered (86.6%)

1876093.78 hits per line

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

91.49
/libs/core/execution_base/include/hpx/execution_base/this_thread.hpp
1
//  Copyright (c) 2019 Thomas Heller
2
//  Copyright (c) 2022 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.hpp>
11
#include <hpx/execution_base/agent_base.hpp>
12
#include <hpx/execution_base/agent_ref.hpp>
13
#include <hpx/execution_base/detail/spinlock_deadlock_detection.hpp>
14
#include <hpx/execution_base/sender.hpp>
15
#include <hpx/functional/detail/tag_fallback_invoke.hpp>
16
#include <hpx/modules/type_support.hpp>
17
#include <hpx/timing/high_resolution_timer.hpp>
18
#include <hpx/timing/steady_clock.hpp>
19
#include <hpx/type_support/meta.hpp>
20

21
#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
22
#include <hpx/errors/throw_exception.hpp>
23
#endif
24

25
#include <chrono>
26
#include <cstddef>
27
#include <cstdint>
28

29
namespace hpx::execution_base {
30

31
    namespace detail {
32

33
        HPX_CORE_EXPORT agent_base& get_default_agent();
34
    }
35

36
    ///////////////////////////////////////////////////////////////////////////
37
    namespace this_thread {
38

39
        namespace detail {
40

41
            struct agent_storage;
42
            HPX_CORE_EXPORT agent_storage* get_agent_storage();
43
        }    // namespace detail
44

45
        struct HPX_CORE_EXPORT reset_agent
46
        {
47
            explicit reset_agent(agent_base& impl);
48
            reset_agent(detail::agent_storage*, agent_base& impl);
49

50
            ~reset_agent();
51

52
            detail::agent_storage* storage_;
53
            agent_base* old_;
54
        };
55

56
        HPX_CORE_EXPORT hpx::execution_base::agent_ref agent();
57

58
        HPX_CORE_EXPORT void yield(
59
            char const* desc = "hpx::execution_base::this_thread::yield");
60
        HPX_CORE_EXPORT void yield_k(std::size_t k,
61
            char const* desc = "hpx::execution_base::this_thread::yield_k");
62
        HPX_CORE_EXPORT void suspend(
63
            char const* desc = "hpx::execution_base::this_thread::suspend");
64

65
        template <typename Rep, typename Period>
66
        void sleep_for(std::chrono::duration<Rep, Period> const& sleep_duration,
1✔
67
            char const* desc = "hpx::execution_base::this_thread::sleep_for")
68
        {
69
            agent().sleep_for(sleep_duration, desc);
1✔
70
        }
1✔
71

72
        template <class Clock, class Duration>
73
        void sleep_until(
1✔
74
            std::chrono::time_point<Clock, Duration> const& sleep_time,
75
            char const* desc = "hpx::execution_base::this_thread::sleep_for")
76
        {
77
            agent().sleep_until(sleep_time, desc);
1✔
78
        }
1✔
79
    }    // namespace this_thread
80
}    // namespace hpx::execution_base
81

82
namespace hpx::this_thread::experimental {
83

84
    // [exec.sched_queries.execute_may_block_caller]
85
    //
86
    // 1. `this_thread::execute_may_block_caller` is used to ask a scheduler s
87
    // whether a call `execution::execute(s, f)` with any invocable f may block
88
    // the thread where such a call occurs.
89
    //
90
    // 2. The name `this_thread::execute_may_block_caller` denotes a
91
    // customization point object. For some subexpression s, let S be
92
    // decltype((s)). If S does not satisfy `execution::scheduler`,
93
    // `this_thread::execute_may_block_caller` is ill-formed. Otherwise,
94
    // `this_thread::execute_may_block_caller(s)` is expression equivalent to:
95
    //
96
    //      1. `tag_invoke(this_thread::execute_may_block_caller, as_const(s))`,
97
    //          if this expression is well formed.
98
    //
99
    //          -- Mandates: The tag_invoke expression above is not
100
    //                       potentially throwing and its type is bool.
101
    //
102
    //      2. Otherwise, true.
103
    //
104
    // 3. If `this_thread::execute_may_block_caller(s)` for some scheduler s
105
    // returns false, no execution::execute(s, f) call with some invocable f
106
    // shall block the calling thread.
107
    namespace detail {
108

109
        // apply this meta function to all tag_invoke variations
110
        struct is_scheduler
111
        {
112
            template <typename EnableTag, typename... T>
113
            using apply = hpx::execution::experimental::is_scheduler<T...>;
114
        };
115
    }    // namespace detail
116

117
    HPX_HOST_DEVICE_INLINE_CONSTEXPR_VARIABLE struct execute_may_block_caller_t
118
        final
119
      : hpx::functional::detail::tag_fallback_noexcept<
120
            execute_may_block_caller_t, detail::is_scheduler>
121
    {
122
    private:
123
        template <typename T>
124
        friend constexpr HPX_FORCEINLINE bool tag_fallback_invoke(
125
            execute_may_block_caller_t, T const&) noexcept
126
        {
127
            return true;
128
        }
129
    } execute_may_block_caller{};
130
}    // namespace hpx::this_thread::experimental
131

132
namespace hpx::util {
133

134
    namespace detail {
135

136
        inline void yield_k(std::size_t k, char const* thread_name)
8,418,681✔
137
        {
138
#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
139
            if (k > 32 && get_spinlock_break_on_deadlock_enabled() &&
8,418,681✔
140
                k > get_spinlock_deadlock_detection_limit())
3,394,557✔
141
            {
142
                HPX_THROW_EXCEPTION(hpx::error::deadlock, thread_name,
×
143
                    "possible deadlock detected");
144
            }
145
#endif
146
            hpx::execution_base::this_thread::yield_k(k, thread_name);
8,418,006✔
147
        }
8,419,159✔
148
    }    // namespace detail
149

150
    template <typename Predicate>
151
    void yield_while(Predicate&& predicate, char const* thread_name = nullptr,
4,461,217✔
152
        bool allow_timed_suspension = true)
153
    {
154
        for (std::size_t k = 0; predicate(); ++k)
11,796,068✔
155
        {
156
            detail::yield_k(allow_timed_suspension ? k : k % 16, thread_name);
7,329,718✔
157
        }
7,334,040✔
158
    }
4,449,736✔
159

160
    namespace detail {
161

162
        // yield_while_count yields until the predicate returns true
163
        // required_count times consecutively. This function is used in cases
164
        // where there is a small false positive rate and repeatedly calling the
165
        // predicate reduces the rate of false positives overall.
166
        //
167
        // Note: This is mostly a hack used to work around the raciness of
168
        // termination detection for thread pools and the runtime and can be
169
        // replaced if and when a better solution appears.
170
        template <typename Predicate>
171
        void yield_while_count(Predicate&& predicate,
4,056✔
172
            std::size_t required_count, char const* thread_name = nullptr,
173
            bool allow_timed_suspension = true)
174
        {
175
            std::size_t count = 0;
4,056✔
176
            for (std::size_t k = 0; /**/; ++k)
1,145,376✔
177
            {
178
                if (!predicate())
1,145,376✔
179
                {
180
                    if (++count > required_count)
46,507✔
181
                    {
182
                        return;
4,056✔
183
                    }
184
                }
42,451✔
185
                else
186
                {
187
                    count = 0;
1,098,869✔
188
                    detail::yield_k(
1,098,869✔
189
                        allow_timed_suspension ? k : k % 16, thread_name);
1,098,869✔
190
                }
191
            }
1,141,320✔
192
        }
193

194
        // yield_while_count_timeout is similar to yield_while_count, with the
195
        // addition of a timeout parameter. If the timeout is exceeded, waiting
196
        // is stopped and the function returns false. If the predicate is
197
        // successfully waited for the function returns true.
198
        template <typename Predicate>
199
        [[nodiscard]] bool yield_while_count_timeout(Predicate&& predicate,
594✔
200
            std::size_t required_count, std::chrono::duration<double> timeout,
201
            char const* thread_name = nullptr,
202
            bool allow_timed_suspension = true)
203
        {
204
            // Seconds represented using a double
205
            using duration_type = std::chrono::duration<double>;
206

207
            // Initialize timer only if needed
208
            bool use_timeout = timeout >= duration_type(0.0);
594✔
209
            hpx::chrono::high_resolution_timer t(
594✔
210
                hpx::chrono::high_resolution_timer::init::no_init);
211

212
            if (use_timeout)
594✔
213
            {
214
                t.restart();
×
215
            }
×
216

217
            std::size_t count = 0;
594✔
218
            for (std::size_t k = 0; /**/; ++k)
6,570✔
219
            {
220
                if (use_timeout && duration_type(t.elapsed()) > timeout)
6,570✔
221
                {
222
                    return false;
×
223
                }
224

225
                if (!predicate())
6,570✔
226
                {
227
                    if (++count > required_count)
6,534✔
228
                    {
229
                        return true;
594✔
230
                    }
231
                }
5,940✔
232
                else
233
                {
234
                    count = 0;
36✔
235
                    detail::yield_k(
36✔
236
                        allow_timed_suspension ? k : k % 16, thread_name);
36✔
237
                }
238
            }
5,976✔
239
        }
594✔
240
    }    // namespace detail
241
}    // namespace hpx::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