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

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

92.86
/libs/core/threading/include/hpx/threading/thread.hpp
1
//  Copyright (c) 2007-2025 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 thread.hpp
8
/// \page hpx::thread, hpx::this_thread::yield, hpx::this_thread::get_id, hpx::this_thread::sleep_for, hpx::this_thread::sleep_until
9
/// \headerfile hpx/thread.hpp
10

11
#pragma once
12

13
#include <hpx/config.hpp>
14
#include <hpx/assert.hpp>
15
#include <hpx/modules/errors.hpp>
16
#include <hpx/modules/functional.hpp>
17
#include <hpx/modules/futures.hpp>
18
#include <hpx/modules/synchronization.hpp>
19
#include <hpx/modules/threading_base.hpp>
20
#include <hpx/modules/timing.hpp>
21

22
#include <cstddef>
23
#include <exception>
24
#include <functional>
25
#include <iosfwd>
26
#include <mutex>
27
#include <type_traits>
28
#include <utility>
29

30
#include <hpx/config/warnings_prefix.hpp>
31

32
///////////////////////////////////////////////////////////////////////////////
33
namespace hpx {
34

35
    ///////////////////////////////////////////////////////////////////////////
36
    HPX_CXX_EXPORT using thread_termination_handler_type =
37
        hpx::function<void(std::exception_ptr const& e)>;
38
    HPX_CXX_EXPORT HPX_CORE_EXPORT void set_thread_termination_handler(
39
        thread_termination_handler_type f);
40

41
    /// The class thread represents a single thread of execution. Threads allow
42
    /// multiple functions to execute concurrently. Threads begin execution
43
    /// immediately upon construction of the associated thread object (pending
44
    /// any OS scheduling delays), starting at the top-level function provided
45
    /// as a constructor argument. The return value of the top-level function is
46
    /// ignored and if it terminates by throwing an exception, \a hpx::terminate
47
    /// is called. The top-level function may communicate its return value or an
48
    /// exception to the caller via \a hpx::promise or by modifying shared
49
    /// variables (which may require synchronization, see hpx::mutex and
50
    /// hpx::atomic) hpx::thread objects may also be in the state that does not
51
    /// represent any thread (after default construction, move from, detach, or
52
    /// join), and a thread of execution may not be associated with any thread
53
    /// objects (after detach). No two hpx::thread objects may represent the
54
    /// same thread of execution; \a hpx::thread is not \a CopyConstructible or
55
    /// \a CopyAssignable, although it is \a MoveConstructible and \a
56
    /// MoveAssignable.
57
    HPX_CXX_EXPORT class HPX_CORE_EXPORT thread
58
    {
59
        using mutex_type = hpx::spinlock;
60

61
        void terminate(char const* function, char const* reason) const;
62

63
    public:
64
        class id;
65
        using native_handle_type = threads::thread_id_type;
66

67
        thread() noexcept;
68

69
        template <typename F,
70
            typename Enable =
71
                std::enable_if_t<!std::is_same_v<std::decay_t<F>, thread>>>
72
        explicit thread(F&& f)
73
        {
74
            auto thrd_data = threads::get_self_id_data();
9✔
75
            HPX_ASSERT(thrd_data);
76
            start_thread(thrd_data->get_scheduler_base()->get_parent_pool(),
9✔
77
                util::deferred_call(HPX_FORWARD(F, f)));
78
        }
6✔
79

6✔
80
        template <typename F, typename... Ts>
9✔
81
        explicit thread(F&& f, Ts&&... vs)
82
        {
83
            auto thrd_data = threads::get_self_id_data();
84
            HPX_ASSERT(thrd_data);
85
            start_thread(thrd_data->get_scheduler_base()->get_parent_pool(),
86
                util::deferred_call(HPX_FORWARD(F, f), HPX_FORWARD(Ts, vs)...));
87
        }
88

89
        template <typename F>
90
        thread(threads::thread_pool_base* pool, F&& f)
91
        {
92
            start_thread(pool, util::deferred_call(HPX_FORWARD(F, f)));
93
        }
94

95
        template <typename F, typename... Ts>
96
        thread(threads::thread_pool_base* pool, F&& f, Ts&&... vs)
97
        {
98
            start_thread(pool,
99
                util::deferred_call(HPX_FORWARD(F, f), HPX_FORWARD(Ts, vs)...));
100
        }
101

102
        ~thread();
103

104
    public:
105
        thread(thread&&) noexcept;
106
        thread& operator=(thread&&) noexcept;
107

108
        /// swaps two thread objects
109
        void swap(thread&) noexcept;
110

111
        /// Checks whether the thread is joinable, i.e. potentially running in
112
        /// parallel context
113
        bool joinable() const noexcept
114
        {
115
            std::lock_guard<mutex_type> l(mtx_);
19✔
116
            return joinable_locked();
117
        }
19✔
118

19✔
119
        /// waits for the thread to finish its execution
120
        void join();
121

122
        /// permits the thread to execute independently of the thread handle
123
        void detach()
124
        {
125
            std::lock_guard<mutex_type> l(mtx_);
126
            detach_locked();
127
        }
128

129
        /// returns the id of the thread
130
        id get_id() const noexcept;
131

132
        /// returns the underlying implementation-defined thread handle
133
        native_handle_type native_handle() const    //-V659
134
        {
135
            std::lock_guard<mutex_type> l(mtx_);
136
            return id_.noref();
137
        }
×
138

139
        /// returns the number of concurrent threads supported by the
140
        /// implementation
141
        [[nodiscard]] static unsigned int hardware_concurrency() noexcept;
142

143
        // extensions
144
        void interrupt(bool flag = true);
145
        bool interruption_requested() const;
146

147
        static void interrupt(id, bool flag = true);
148

149
        hpx::future<void> get_future(error_code& ec = throws);
150

151
        std::size_t get_thread_data() const;
152
        std::size_t set_thread_data(std::size_t);
153

154
#if defined(HPX_HAVE_LIBCDS)
155
        std::size_t get_libcds_data() const;
156
        std::size_t set_libcds_data(std::size_t);
157
        std::size_t get_libcds_hazard_pointer_data() const;
158
        std::size_t set_libcds_hazard_pointer_data(std::size_t);
159
        std::size_t get_libcds_dynamic_hazard_pointer_data() const;
160
        std::size_t set_libcds_dynamic_hazard_pointer_data(std::size_t);
161
#endif
162

163
    private:
164
        bool joinable_locked() const noexcept
165
        {
166
            return threads::invalid_thread_id != id_;
167
        }
168

169
        void detach_locked()
170
        {
171
            id_ = threads::invalid_thread_id;
172
        }
173

174
        void start_thread(threads::thread_pool_base* pool,
175
            hpx::move_only_function<void()>&& func);
176

177
        static threads::thread_result_type thread_function_nullary(
178
            hpx::move_only_function<void()> const& func);
179

180
        mutable mutex_type mtx_;
181
        threads::thread_id_ref_type id_;
182
    };
183

184
    HPX_CXX_EXPORT inline void swap(thread& x, thread& y) noexcept
185
    {
186
        x.swap(y);
187
    }
188

189
    class thread::id
190
    {
191
    private:
192
        threads::thread_id_type id_;
193

194
        friend bool operator==(
195
            thread::id const& x, thread::id const& y) noexcept;
196
        friend bool operator!=(
197
            thread::id const& x, thread::id const& y) noexcept;
198
        friend bool operator<(
199
            thread::id const& x, thread::id const& y) noexcept;
200
        friend bool operator>(
201
            thread::id const& x, thread::id const& y) noexcept;
202
        friend bool operator<=(
203
            thread::id const& x, thread::id const& y) noexcept;
204
        friend bool operator>=(
205
            thread::id const& x, thread::id const& y) noexcept;
206

207
        template <typename Char, typename Traits>
208
        friend std::basic_ostream<Char, Traits>& operator<<(
209
            std::basic_ostream<Char, Traits>&, thread::id const&);
210

211
        friend class thread;
212

213
    public:
214
        id() noexcept = default;
215

216
        explicit id(threads::thread_id_type const& i) noexcept
217
          : id_(i)
218
        {
219
        }
6✔
220
        explicit id(threads::thread_id_type&& i) noexcept
221
          : id_(HPX_MOVE(i))
222
        {
223
        }
224

225
        explicit id(threads::thread_id_ref_type const& i) noexcept
226
          : id_(i.get().get())
227
        {
228
        }
229
        explicit id(threads::thread_id_ref_type&& i) noexcept
230
          : id_(HPX_MOVE(i).get().get())
231
        {
232
        }
233

234
        threads::thread_id_type const& native_handle() const noexcept
235
        {
236
            return id_;
237
        }
238
    };
239

240
    HPX_CXX_EXPORT inline bool operator==(
241
        thread::id const& x, thread::id const& y) noexcept
242
    {
243
        return x.id_ == y.id_;
244
    }
245

246
    HPX_CXX_EXPORT inline bool operator!=(
247
        thread::id const& x, thread::id const& y) noexcept
248
    {
249
        return !(x == y);
250
    }
251

252
    HPX_CXX_EXPORT inline bool operator<(
253
        thread::id const& x, thread::id const& y) noexcept
254
    {
255
        return x.id_ < y.id_;
256
    }
257

258
    HPX_CXX_EXPORT inline bool operator>(
259
        thread::id const& x, thread::id const& y) noexcept
260
    {
261
        return y < x;
262
    }
263

264
    HPX_CXX_EXPORT inline bool operator<=(
265
        thread::id const& x, thread::id const& y) noexcept
266
    {
267
        return !(x > y);
268
    }
269

270
    HPX_CXX_EXPORT inline bool operator>=(
271
        thread::id const& x, thread::id const& y) noexcept
272
    {
273
        return !(x < y);
274
    }
275

276
    HPX_CXX_EXPORT template <typename Char, typename Traits>
11✔
277
    std::basic_ostream<Char, Traits>& operator<<(
278
        std::basic_ostream<Char, Traits>& out, thread::id const& id)
279
    {
280
        out << id.id_;
281
        return out;
282
    }
283

284
    ///////////////////////////////////////////////////////////////////////////
285
    namespace this_thread {
286

287
        /// \brief Returns the id of the current thread
288
        HPX_CXX_EXPORT HPX_CORE_EXPORT thread::id get_id() noexcept;
289

290
        /// Provides a hint to the implementation to reschedule the execution of
291
        /// threads, allowing other threads to run.
292
        ///
293
        /// \note  The exact behavior of this function depends on the
294
        ///        implementation, in particular on the mechanics of the OS
295
        ///        scheduler in use and the state of the system. For example, a
296
        ///        first-in-first-out realtime scheduler (SCHED_FIFO in Linux)
297
        ///        would suspend the current thread and put it on the back of
298
        ///        the queue of the same-priority threads that are ready to run
299
        ///        (and if there are no other threads at the same priority,
300
        ///        yield has no effect).
301
        HPX_CXX_EXPORT HPX_CORE_EXPORT void yield() noexcept;
302
        HPX_CXX_EXPORT HPX_CORE_EXPORT void yield_to(thread::id) noexcept;
303

304
        // extensions
305
        HPX_CXX_EXPORT HPX_CORE_EXPORT threads::thread_priority
306
        get_priority() noexcept;
307
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::ptrdiff_t get_stack_size() noexcept;
308

309
        HPX_CXX_EXPORT HPX_CORE_EXPORT void interruption_point();
310
        HPX_CXX_EXPORT HPX_CORE_EXPORT bool interruption_enabled();
311
        HPX_CXX_EXPORT HPX_CORE_EXPORT bool interruption_requested();
312

313
        HPX_CXX_EXPORT HPX_CORE_EXPORT void interrupt();
314

315
        /// Blocks the execution of the current thread until specified
316
        /// \a abs_time has been reached.
317
        ///
318
        /// \details It is recommended to use the clock tied to \a abs_time, in
319
        ///          which case adjustments of the clock may be taken into
320
        ///          account. Thus, the duration of the block might be more or
321
        ///          less than \c abs_time-Clock::now() at the time of the call,
322
        ///          depending on the direction of the adjustment and whether it
323
        ///          is honored by the implementation. The function also may
324
        ///          block until after \a abs_time has been reached due to
325
        ///          process scheduling or resource contention delays.
326
        /// \param abs_time absolute time to block until
327
        HPX_CXX_EXPORT HPX_CORE_EXPORT void sleep_until(
328
            hpx::chrono::steady_time_point const& abs_time);
329

330
        /// Blocks the execution of the current thread for at least the
331
        /// specified \a rel_time. This function may block for longer than \a
332
        /// rel_time due to scheduling or resource contention delays.
333
        ///
129✔
334
        /// \details It is recommended to use a steady clock to measure the
335
        ///          duration. If an implementation uses a system clock instead,
129✔
336
        ///          the wait time may also be sensitive to clock adjustments.
129✔
337
        /// \param rel_time time duration to sleep
338
        HPX_CXX_EXPORT inline void sleep_for(
339
            hpx::chrono::steady_duration const& rel_time)
340
        {
341
            sleep_until(rel_time.from_now());
342
        }
343

344
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t get_thread_data();
345
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t set_thread_data(std::size_t);
346

347
#if defined(HPX_HAVE_LIBCDS)
348
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t get_libcds_data();
349
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t set_libcds_data(std::size_t);
350
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t
351
        get_libcds_hazard_pointer_data();
352
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t
353
        set_libcds_hazard_pointer_data(std::size_t);
354
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t
355
        get_libcds_dynamic_hazard_pointer_data();
356
        HPX_CXX_EXPORT HPX_CORE_EXPORT std::size_t
357
        set_libcds_dynamic_hazard_pointer_data(std::size_t);
358
#endif
359

360
        HPX_CXX_EXPORT class HPX_CORE_EXPORT disable_interruption
361
        {
362
        private:
363
            disable_interruption(disable_interruption const&);
364
            disable_interruption& operator=(disable_interruption const&);
365

366
            bool interruption_was_enabled_;
367
            friend class restore_interruption;
368

369
        public:
370
            disable_interruption();
371
            ~disable_interruption();
372
        };
373

374
        HPX_CXX_EXPORT class HPX_CORE_EXPORT restore_interruption
375
        {
376
        private:
377
            restore_interruption(restore_interruption const&);
378
            restore_interruption& operator=(restore_interruption const&);
379

380
            bool interruption_was_enabled_;
381

382
        public:
383
            explicit restore_interruption(disable_interruption& d);
384
            ~restore_interruption();
385
        };
386
    }    // namespace this_thread
387
}    // namespace hpx
388

389
// specialize std::hash for hpx::thread::id
390
template <>
391
struct std::hash<::hpx::thread::id>
392
{
393
    std::size_t operator()(::hpx::thread::id const& id) const noexcept
394
    {
395
        std::hash<::hpx::threads::thread_id_ref_type> hasher_;
396
        return hasher_(id.native_handle());
397
    }
398
};
399

400
#include <hpx/config/warnings_suffix.hpp>
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