• 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

82.64
/libs/core/threading_base/src/thread_data.cpp
1
//  Copyright (c) 2007-2021 Hartmut Kaiser
2
//  Copyright (c) 2008-2009 Chirag Dekate, Anshul Tandon
3
//  Copyright (c) 2011      Bryce Lelbach
4
//
5
//  SPDX-License-Identifier: BSL-1.0
6
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
7
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8

9
#include <hpx/assert.hpp>
10
#include <hpx/coroutines/detail/coroutine_accessor.hpp>
11
#include <hpx/functional/function.hpp>
12
#include <hpx/lock_registration/detail/register_locks.hpp>
13
#include <hpx/modules/errors.hpp>
14
#include <hpx/modules/logging.hpp>
15
#include <hpx/thread_support/unlock_guard.hpp>
16
#include <hpx/threading_base/scheduler_base.hpp>
17
#include <hpx/threading_base/thread_data.hpp>
18
#if defined(HPX_HAVE_APEX)
19
#include <hpx/threading_base/external_timer.hpp>
20
#endif
21

22
#include <cstddef>
23
#include <cstdint>
24
#include <memory>
25

26
////////////////////////////////////////////////////////////////////////////////
27
namespace hpx { namespace threads {
28
    namespace detail {
29
        static get_locality_id_type* get_locality_id_f;
30

31
        void set_get_locality_id(get_locality_id_type* f)
1,219✔
32
        {
33
            get_locality_id_f = f;
1,219✔
34
        }
1,219✔
35

36
        std::uint32_t get_locality_id(hpx::error_code& ec)
×
37
        {
38
            if (get_locality_id_f)
×
39
            {
40
                return get_locality_id_f(ec);
×
41
            }
42

43
            // same as naming::invalid_locality_id
44
            return ~static_cast<std::uint32_t>(0);
×
45
        }
×
46
    }    // namespace detail
47

48
    thread_data::thread_data(thread_init_data& init_data, void* queue,
682,519✔
49
        std::ptrdiff_t stacksize, bool is_stackless, thread_id_addref addref)
50
      : detail::thread_data_reference_counting(addref)
341,204✔
51
      , current_state_(thread_state(
682,630✔
52
            init_data.initial_state, thread_restart_state::signaled))
341,204✔
53
#ifdef HPX_HAVE_THREAD_DESCRIPTION
54
      , description_(init_data.description)
55
      , lco_description_()
56
#endif
57
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
58
      , parent_locality_id_(init_data.parent_locality_id)
59
      , parent_thread_id_(init_data.parent_id)
60
      , parent_thread_phase_(init_data.parent_phase)
61
#endif
62
#ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
63
      , marked_state_(thread_schedule_state::unknown)
64
#endif
65
#ifdef HPX_HAVE_THREAD_BACKTRACE_ON_SUSPENSION
66
      , backtrace_(nullptr)
67
#endif
68
      , priority_(init_data.priority)
341,137✔
69
      , requested_interrupt_(false)
341,137✔
70
      , enabled_interrupt_(true)
341,137✔
71
      , ran_exit_funcs_(false)
341,137✔
72
      , is_stackless_(is_stackless)
341,137✔
73
      , scheduler_base_(init_data.scheduler_base)
341,137✔
74
      , last_worker_thread_num_(std::size_t(-1))
341,137✔
75
      , stacksize_(stacksize)
341,137✔
76
      , stacksize_enum_(init_data.stacksize)
341,137✔
77
      , queue_(queue)
341,137✔
78
    {
682,630✔
79
        LTM_(debug).format(
341,204✔
80
            "thread::thread({}), description({})", this, get_description());
319,772✔
81

82
        HPX_ASSERT(stacksize_enum_ != threads::thread_stacksize::current);
341,258✔
83

84
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
85
        // store the thread id of the parent thread, mainly for debugging
86
        // purposes
87
        if (parent_thread_id_ == nullptr)
88
        {
89
            thread_self* self = get_self_ptr();
90
            if (self)
91
            {
92
                parent_thread_id_ = threads::get_self_id();
93
                parent_thread_phase_ = self->get_thread_phase();
94
            }
95
        }
96
        if (0 == parent_locality_id_)
97
            parent_locality_id_ = detail::get_locality_id(hpx::throws);
98
#endif
99
#if defined(HPX_HAVE_APEX)
100
        set_timer_data(init_data.timer_data);
101
#endif
102
    }
341,227✔
103

104
    thread_data::~thread_data()
341,313✔
105
    {
341,313✔
106
        LTM_(debug).format("thread_data::~thread_data({})", this);
341,313✔
107
        free_thread_exit_callbacks();
341,313✔
108
    }
341,313✔
109

110
    void thread_data::destroy_thread()
5,716,447✔
111
    {
112
        LTM_(debug).format(
5,716,447✔
113
            "thread_data::destroy_thread({}), description({}), phase({})", this,
5,707,046✔
114
            this->get_description(), this->get_thread_phase());
5,707,116✔
115

116
        get_scheduler_base()->destroy_thread(this);
5,716,399✔
117
    }
5,716,404✔
118

119
    void thread_data::run_thread_exit_callbacks()
4,828,888✔
120
    {
121
        std::unique_lock<hpx::util::detail::spinlock> l(
4,829,025✔
122
            spinlock_pool::spinlock_for(this));
4,829,025✔
123

124
        while (!exit_funcs_.empty())
4,829,270✔
125
        {
126
            {
127
                hpx::unlock_guard<std::unique_lock<hpx::util::detail::spinlock>>
128
                    ul(l);
382✔
129
                if (!exit_funcs_.front().empty())
382✔
130
                    exit_funcs_.front()();
382✔
131
            }
382✔
132
            exit_funcs_.pop_front();
382✔
133
        }
134
        ran_exit_funcs_ = true;
4,828,983✔
135
    }
4,828,981✔
136

137
    bool thread_data::add_thread_exit_callback(hpx::function<void()> const& f)
1,135✔
138
    {
139
        std::lock_guard<hpx::util::detail::spinlock> l(
1,135✔
140
            spinlock_pool::spinlock_for(this));
1,135✔
141

142
        if (ran_exit_funcs_ ||
1,517✔
143
            get_state().state() == thread_schedule_state::terminated)
382✔
144
        {
145
            return false;
753✔
146
        }
147

148
        exit_funcs_.push_front(f);
382✔
149

150
        return true;
382✔
151
    }
1,135✔
152

153
    void thread_data::free_thread_exit_callbacks()
10,681,329✔
154
    {
155
        std::lock_guard<hpx::util::detail::spinlock> l(
10,682,006✔
156
            spinlock_pool::spinlock_for(this));
10,682,006✔
157

158
        // Exit functions should have been executed.
159
        HPX_ASSERT(exit_funcs_.empty() || ran_exit_funcs_);
10,681,329✔
160

161
        exit_funcs_.clear();
10,681,775✔
162
    }
10,681,775✔
163

164
    bool thread_data::interruption_point(bool throw_on_interrupt)
161,908,585✔
165
    {
166
        // We do not protect enabled_interrupt_ and requested_interrupt_
167
        // from concurrent access here (which creates a benign data race) in
168
        // order to avoid infinite recursion. This function is called by
169
        // this_thread::suspend which causes problems if the lock would call
170
        // suspend itself.
171
        if (enabled_interrupt_ && requested_interrupt_)
161,908,585✔
172
        {
173
            // Verify that there are no more registered locks for this
174
            // OS-thread. This will throw if there are still any locks
175
            // held.
176
            util::force_error_on_lock();
5✔
177

178
            // now interrupt this thread
179
            if (throw_on_interrupt)
5✔
180
            {
181
                requested_interrupt_ = false;    // avoid recursive exceptions
×
182
                throw hpx::thread_interrupted();
×
183
            }
184

185
            return true;
×
186
        }
187
        return false;
162,153,062✔
188
    }
162,160,124✔
189

190
    void thread_data::rebind_base(thread_init_data& init_data)
5,512,322✔
191
    {
192
        LTM_(debug).format(
5,512,322✔
193
            "thread_data::rebind_base({}), description({}), phase({}), rebind",
5,506,662✔
194
            this, get_description(), get_thread_phase());
5,506,792✔
195

196
        free_thread_exit_callbacks();
5,512,726✔
197

198
        current_state_.store(thread_state(
11,025,438✔
199
            init_data.initial_state, thread_restart_state::signaled));
5,512,726✔
200

201
#ifdef HPX_HAVE_THREAD_DESCRIPTION
202
        description_ = init_data.description;
203
        lco_description_ = util::thread_description();
204
#endif
205
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
206
        parent_locality_id_ = init_data.parent_locality_id;
207
        parent_thread_id_ = init_data.parent_id;
208
        parent_thread_phase_ = init_data.parent_phase;
209
#endif
210
#ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
211
        set_marked_state(thread_schedule_state::unknown);
212
#endif
213
#ifdef HPX_HAVE_THREAD_BACKTRACE_ON_SUSPENSION
214
        backtrace_ = nullptr;
215
#endif
216
        priority_ = init_data.priority;
5,512,726✔
217
        requested_interrupt_ = false;
5,512,726✔
218
        enabled_interrupt_ = true;
5,512,726✔
219
        ran_exit_funcs_ = false;
5,512,726✔
220
        exit_funcs_.clear();
5,512,726✔
221
        scheduler_base_ = init_data.scheduler_base;
5,512,726✔
222
        last_worker_thread_num_ = std::size_t(-1);
5,512,726✔
223

224
        // We explicitly set the logical stack size again as it can be different
225
        // from what the previous use required. However, the physical stack size
226
        // must be the same as before.
227
        stacksize_enum_ = init_data.stacksize;
5,512,726✔
228
        HPX_ASSERT(stacksize_ == get_stack_size());
5,512,719✔
229
        HPX_ASSERT(stacksize_ != 0);
5,512,725✔
230

231
        LTM_(debug).format("thread::thread({}), description({}), rebind", this,
5,512,725✔
232
            get_description());
5,507,167✔
233

234
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
235
        // store the thread id of the parent thread, mainly for debugging
236
        // purposes
237
        if (parent_thread_id_ == nullptr)
238
        {
239
            thread_self* self = get_self_ptr();
240
            if (self)
241
            {
242
                parent_thread_id_ = threads::get_self_id();
243
                parent_thread_phase_ = self->get_thread_phase();
244
            }
245
        }
246
        if (0 == parent_locality_id_)
247
        {
248
            parent_locality_id_ = detail::get_locality_id(hpx::throws);
249
        }
250
#endif
251
#if defined(HPX_HAVE_APEX)
252
        set_timer_data(init_data.timer_data);
253
#endif
254
    }
5,512,689✔
255

256
    ///////////////////////////////////////////////////////////////////////////
257
    thread_self& get_self()
2,114,666✔
258
    {
259
        thread_self* p = get_self_ptr();
2,114,666✔
260
        if (HPX_UNLIKELY(p == nullptr))
2,114,623✔
261
        {
262
            HPX_THROW_EXCEPTION(hpx::error::null_thread_id, "threads::get_self",
×
263
                "null thread id encountered (is this executed on a "
264
                "HPX-thread?)");
265
        }
266
        return *p;
2,114,618✔
267
    }
×
268

269
    thread_self* get_self_ptr()
658,747,224✔
270
    {
271
        return thread_self::get_self();
658,747,224✔
272
    }
273

274
    namespace detail {
275
        void set_self_ptr(thread_self* self)
×
276
        {
277
            thread_self::set_self(self);
×
278
        }
×
279
    }    // namespace detail
280

281
    thread_self::impl_type* get_ctx_ptr()
8✔
282
    {
283
        using hpx::threads::coroutines::detail::coroutine_accessor;
284
        return coroutine_accessor::get_impl(get_self());
8✔
285
    }
286

287
    thread_self* get_self_ptr_checked(error_code& ec)
×
288
    {
289
        thread_self* p = thread_self::get_self();
×
290

291
        if (HPX_UNLIKELY(p == nullptr))
×
292
        {
293
            HPX_THROWS_IF(ec, hpx::error::null_thread_id,
×
294
                "threads::get_self_ptr_checked",
295
                "null thread id encountered (is this executed on a "
296
                "HPX-thread?)");
297
            return nullptr;
×
298
        }
299

300
        if (&ec != &throws)
×
301
            ec = make_success_code();
×
302

303
        return p;
×
304
    }
×
305

306
    thread_id_type get_self_id()
18,807,457✔
307
    {
308
        thread_self* self = get_self_ptr();
18,804,978✔
309
        if (HPX_LIKELY(nullptr != self))
18,804,978✔
310
            return self->get_thread_id();
18,802,979✔
311

312
        return threads::invalid_thread_id;
1,677✔
313
    }
18,804,515✔
314

315
    thread_data* get_self_id_data()
9,711,059✔
316
    {
317
        thread_self* self = get_self_ptr();
9,711,059✔
318
        if (HPX_LIKELY(nullptr != self))
9,710,992✔
319
            return get_thread_id_data(self->get_thread_id());
8,505,730✔
320

321
        return nullptr;
1,205,191✔
322
    }
9,710,771✔
323

324
    std::ptrdiff_t get_self_stacksize()
×
325
    {
326
        thread_data* thrd_data = get_self_id_data();
×
327
        return thrd_data ? thrd_data->get_stack_size() : 0;
×
328
    }
329

330
    thread_stacksize get_self_stacksize_enum()
690✔
331
    {
332
        thread_data* thrd_data = get_self_id_data();
690✔
333
        thread_stacksize stacksize = thrd_data ?
690✔
334
            thrd_data->get_stack_size_enum() :
493✔
335
            thread_stacksize::default_;
336
        HPX_ASSERT(stacksize != thread_stacksize::current);
690✔
337
        return stacksize;
690✔
338
    }
339

340
#ifndef HPX_HAVE_THREAD_PARENT_REFERENCE
341
    thread_id_type get_parent_id()
57,172,511✔
342
    {
343
        return threads::invalid_thread_id;
57,172,285✔
344
    }
345

346
    std::size_t get_parent_phase()
57,192,491✔
347
    {
348
        return 0;
57,192,491✔
349
    }
350

351
    std::uint32_t get_parent_locality_id()
57,164,755✔
352
    {
353
        // same as naming::invalid_locality_id
354
        return ~static_cast<std::uint32_t>(0);
57,164,755✔
355
    }
356
#else
357
    thread_id_type get_parent_id()
358
    {
359
        thread_data* thrd_data = get_self_id_data();
360
        if (HPX_LIKELY(nullptr != thrd_data))
361
        {
362
            return thrd_data->get_parent_thread_id();
363
        }
364
        return threads::invalid_thread_id;
365
    }
366

367
    std::size_t get_parent_phase()
368
    {
369
        thread_data* thrd_data = get_self_id_data();
370
        if (HPX_LIKELY(nullptr != thrd_data))
371
        {
372
            return thrd_data->get_parent_thread_phase();
373
        }
374
        return 0;
375
    }
376

377
    std::uint32_t get_parent_locality_id()
378
    {
379
        thread_data* thrd_data = get_self_id_data();
380
        if (HPX_LIKELY(nullptr != thrd_data))
381
        {
382
            return thrd_data->get_parent_locality_id();
383
        }
384

385
        // same as naming::invalid_locality_id
386
        return ~static_cast<std::uint32_t>(0);
387
    }
388
#endif
389

390
    std::uint64_t get_self_component_id()
31,208,019✔
391
    {
392
#ifndef HPX_HAVE_THREAD_TARGET_ADDRESS
393
        return 0;
31,208,019✔
394
#else
395
        thread_data* thrd_data = get_self_id_data();
396
        if (HPX_LIKELY(nullptr != thrd_data))
397
        {
398
            return thrd_data->get_component_id();
399
        }
400
        return 0;
401
#endif
402
    }
403

404
#if defined(HPX_HAVE_APEX)
405
    std::shared_ptr<hpx::util::external_timer::task_wrapper>
406
    get_self_timer_data()
407
    {
408
        thread_data* thrd_data = get_self_id_data();
409
        if (HPX_LIKELY(nullptr != thrd_data))
410
        {
411
            return thrd_data->get_timer_data();
412
        }
413
        return nullptr;
414
    }
415
    void set_self_timer_data(
416
        std::shared_ptr<hpx::util::external_timer::task_wrapper> data)
417
    {
418
        thread_data* thrd_data = get_self_id_data();
419
        if (HPX_LIKELY(nullptr != thrd_data))
420
        {
421
            thrd_data->set_timer_data(data);
422
        }
423
        return;
424
    }
425
#endif
426
}}    // namespace hpx::threads
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