• 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

68.57
/libs/core/runtime_local/src/runtime_local.cpp
1
//  Copyright (c) 2007-2022 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
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
#include <hpx/config.hpp>
9
#include <hpx/assert.hpp>
10
#include <hpx/command_line_handling_local/late_command_line_handling_local.hpp>
11
#include <hpx/command_line_handling_local/parse_command_line_local.hpp>
12
#include <hpx/coroutines/coroutine.hpp>
13
#include <hpx/coroutines/signal_handler_debugging.hpp>
14
#include <hpx/debugging/backtrace.hpp>
15
#include <hpx/execution_base/this_thread.hpp>
16
#include <hpx/functional/bind.hpp>
17
#include <hpx/functional/function.hpp>
18
#include <hpx/itt_notify/thread_name.hpp>
19
#include <hpx/modules/errors.hpp>
20
#include <hpx/modules/logging.hpp>
21
#include <hpx/modules/threadmanager.hpp>
22
#include <hpx/runtime_local/config_entry.hpp>
23
#include <hpx/runtime_local/custom_exception_info.hpp>
24
#include <hpx/runtime_local/debugging.hpp>
25
#include <hpx/runtime_local/os_thread_type.hpp>
26
#include <hpx/runtime_local/runtime_local.hpp>
27
#include <hpx/runtime_local/runtime_local_fwd.hpp>
28
#include <hpx/runtime_local/shutdown_function.hpp>
29
#include <hpx/runtime_local/startup_function.hpp>
30
#include <hpx/runtime_local/state.hpp>
31
#include <hpx/runtime_local/thread_hooks.hpp>
32
#include <hpx/runtime_local/thread_mapper.hpp>
33
#include <hpx/static_reinit/static_reinit.hpp>
34
#include <hpx/thread_support/set_thread_name.hpp>
35
#include <hpx/threading_base/external_timer.hpp>
36
#include <hpx/threading_base/scheduler_mode.hpp>
37
#include <hpx/timing/high_resolution_clock.hpp>
38
#include <hpx/topology/topology.hpp>
39
#include <hpx/util/from_string.hpp>
40
#include <hpx/version.hpp>
41

42
#include <atomic>
43
#include <condition_variable>
44
#include <cstddef>
45
#include <cstdint>
46
#include <cstring>
47
#include <exception>
48
#include <functional>
49
#include <iomanip>
50
#include <iostream>
51
#include <list>
52
#include <memory>
53
#include <mutex>
54
#include <sstream>
55
#include <string>
56
#include <thread>
57
#include <utility>
58

59
///////////////////////////////////////////////////////////////////////////////
60
// Make sure the system gets properly shut down while handling Ctrl-C and other
61
// system signals
62
#if defined(HPX_WINDOWS)
63

64
namespace hpx {
65
    ///////////////////////////////////////////////////////////////////////////
66
    void handle_termination(char const* reason)
67
    {
68
        if (hpx::threads::coroutines::attach_debugger_on_sigv)
69
        {
70
            util::attach_debugger();
71
        }
72

73
        if (hpx::threads::coroutines::diagnostics_on_terminate)
74
        {
75
            int const verbosity = hpx::threads::coroutines::exception_verbosity;
76

77
            if (verbosity >= 2)
78
            {
79
                std::cerr << full_build_string() << "\n";
80
            }
81

82
#if defined(HPX_HAVE_STACKTRACES)
83
            if (verbosity >= 1)
84
            {
85
                std::size_t const trace_depth =
86
                    util::from_string<std::size_t>(get_config_entry(
87
                        "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
88
                std::cerr << "{stack-trace}: " << hpx::util::trace(trace_depth)
89
                          << "\n";
90
            }
91
#endif
92

93
            std::cerr << "{what}: " << (reason ? reason : "Unknown reason")
94
                      << "\n";
95
        }
96
    }
97

98
    HPX_CORE_EXPORT BOOL WINAPI termination_handler(DWORD ctrl_type)
99
    {
100
        switch (ctrl_type)
101
        {
102
        case CTRL_C_EVENT:
103
            handle_termination("Ctrl-C");
104
            break;
105

106
        case CTRL_BREAK_EVENT:
107
            handle_termination("Ctrl-Break");
108
            break;
109

110
        case CTRL_CLOSE_EVENT:
111
            handle_termination("Ctrl-Close");
112
            break;
113

114
        case CTRL_LOGOFF_EVENT:
115
            handle_termination("Logoff");
116
            break;
117

118
        case CTRL_SHUTDOWN_EVENT:
119
            handle_termination("Shutdown");
120
            break;
121

122
        default:
123
            break;
124
        }
125
        return FALSE;
126
    }
127
}    // namespace hpx
128

129
#else
130

131
#include <signal.h>
132
#include <stdlib.h>
133
#include <string.h>
134

135
namespace hpx {
136
    ///////////////////////////////////////////////////////////////////////////
137
    [[noreturn]] HPX_CORE_EXPORT void termination_handler(int signum)
×
138
    {
139
        if (signum != SIGINT &&
×
140
            hpx::threads::coroutines::attach_debugger_on_sigv)
×
141
        {
142
            util::attach_debugger();
×
143
        }
×
144

145
        if (hpx::threads::coroutines::diagnostics_on_terminate)
×
146
        {
147
            int const verbosity = hpx::threads::coroutines::exception_verbosity;
×
148
            char* reason = strsignal(signum);
×
149

150
            if (verbosity >= 2)
×
151
            {
152
                std::cerr << full_build_string() << "\n";
×
153
            }
×
154

155
#if defined(HPX_HAVE_STACKTRACES)
156
            if (verbosity >= 1)
×
157
            {
158
                std::size_t const trace_depth =
×
159
                    util::from_string<std::size_t>(get_config_entry(
×
160
                        "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
×
161
                std::cerr << "{stack-trace}: " << hpx::util::trace(trace_depth)
×
162
                          << "\n";
×
163
            }
×
164
#endif
165

166
            std::cerr << "{what}: " << (reason ? reason : "Unknown reason")
×
167
                      << "\n";
×
168
        }
×
169
        std::abort();
×
170
    }
×
171
}    // namespace hpx
172

173
#endif
174

175
///////////////////////////////////////////////////////////////////////////////
176
namespace hpx {
177

178
    ///////////////////////////////////////////////////////////////////////////
179
    HPX_CORE_EXPORT void HPX_CDECL new_handler()
×
180
    {
181
        HPX_THROW_EXCEPTION(hpx::error::out_of_memory, "new_handler",
×
182
            "new allocator failed to allocate memory");
183
    }
×
184

185
    ///////////////////////////////////////////////////////////////////////////
186
    namespace detail {
187
        // Sometimes the HPX library gets simply unloaded as a result of some
188
        // extreme error handling. Avoid hangs in the end by setting a flag.
189
        static bool exit_called = false;
190

191
        void on_exit() noexcept
1,219✔
192
        {
193
            exit_called = true;
1,219✔
194
        }
1,219✔
195

196
        void on_abort(int) noexcept
1✔
197
        {
198
            exit_called = true;
×
199
            std::exit(-1);
×
200
        }
201
    }    // namespace detail
202

203
    ///////////////////////////////////////////////////////////////////////////
204
    void set_error_handlers()
1,219✔
205
    {
206
        // initialize global variables
207
        hpx::threads::coroutines::attach_debugger_on_sigv =
1,219✔
208
            get_config_entry("hpx.attach_debugger", "") == "exception";
1,219✔
209
        hpx::threads::coroutines::diagnostics_on_terminate =
1,219✔
210
            get_config_entry("hpx.diagnostics_on_terminate", "1") == "1";
1,219✔
211
        hpx::threads::coroutines::exception_verbosity = util::from_string<int>(
1,219✔
212
            get_config_entry("hpx.exception_verbosity", "2"));
1,219✔
213
        hpx::threads::coroutines::exception_verbosity = 0;
1,219✔
214
#if defined(HPX_HAVE_STACKTRACES) && defined(HPX_HAVE_THREAD_BACKTRACE_DEPTH)
215
        hpx::threads::coroutines::exception_verbosity =
1,219✔
216
            util::from_string<int>(get_config_entry(
1,219✔
217
                "hpx.trace_depth", HPX_HAVE_THREAD_BACKTRACE_DEPTH));
1,219✔
218
#endif
219

220
#if defined(HPX_WINDOWS)
221
        // Set console control handler to allow server to be stopped.
222
        SetConsoleCtrlHandler(hpx::termination_handler, TRUE);
223
#else
224
        if (util::from_string<int>(get_config_entry("hpx.handle_signals", 1)))
1,219✔
225
        {
226
            struct sigaction new_action;
227
            new_action.sa_handler = hpx::termination_handler;
1,219✔
228
            sigemptyset(&new_action.sa_mask);
1,219✔
229
            new_action.sa_flags = 0;
1,219✔
230

231
            sigaction(SIGINT, &new_action, nullptr);    // Interrupted
1,219✔
232
            sigaction(SIGBUS, &new_action, nullptr);    // Bus error
1,219✔
233
            sigaction(
1,219✔
234
                SIGFPE, &new_action, nullptr);    // Floating point exception
235
            sigaction(SIGILL, &new_action, nullptr);     // Illegal instruction
1,219✔
236
            sigaction(SIGPIPE, &new_action, nullptr);    // Bad pipe
1,219✔
237
            sigaction(SIGSEGV, &new_action, nullptr);    // Segmentation fault
1,219✔
238
            sigaction(SIGSYS, &new_action, nullptr);     // Bad syscall
1,219✔
239

240
            hpx::threads::coroutines::register_signal_handler = false;
1,219✔
241
        }
1,219✔
242
        else
243
        {
244
            hpx::threads::coroutines::register_signal_handler = true;
×
245
        }
246
#endif
247

248
        std::set_new_handler(hpx::new_handler);
1,219✔
249
    }
1,219✔
250

251
    ///////////////////////////////////////////////////////////////////////////
252
    namespace strings {
253
        inline constexpr char const* const runtime_state_names[] = {
254
            "state::invalid",         // -1
255
            "state::initialized",     // 0
256
            "state::pre_startup",     // 1
257
            "state::startup",         // 2
258
            "state::pre_main",        // 3
259
            "state::starting",        // 4
260
            "state::running",         // 5
261
            "state::suspended",       // 6
262
            "state::pre_sleep",       // 7
263
            "state::sleeping",        // 8
264
            "state::pre_shutdown",    // 9
265
            "state::shutdown",        // 10
266
            "state::stopping",        // 11
267
            "state::terminating",     // 12
268
            "state::stopped"          // 13
269
        };
270
    }
271

272
    char const* get_runtime_state_name(state s)
2,526✔
273
    {
274
        if (s < state::invalid || s >= state::last_valid_runtime_state)
2,526✔
275
        {
276
            return "invalid (value out of bounds)";
×
277
        }
278
        return strings::runtime_state_names[static_cast<int>(s) + 1];
2,526✔
279
    }
2,526✔
280

281
    ///////////////////////////////////////////////////////////////////////////
282
    threads::policies::callback_notifier::on_startstop_type
283
        global_on_start_func;
1,249✔
284
    threads::policies::callback_notifier::on_startstop_type global_on_stop_func;
1,249✔
285
    threads::policies::callback_notifier::on_error_type global_on_error_func;
1,249✔
286

287
    ///////////////////////////////////////////////////////////////////////////
288
    runtime::runtime(hpx::util::runtime_configuration& rtcfg, bool initialize)
2,496✔
289
      : rtcfg_(rtcfg)
624✔
290
      , instance_number_(++instance_number_counter_)
624✔
291
      , thread_support_(new util::thread_mapper)
624✔
292
      , topology_(resource::get_partitioner().get_topology())
624✔
293
      , state_(state::invalid)
624✔
294
      , on_start_func_(global_on_start_func)
624✔
295
      , on_stop_func_(global_on_stop_func)
624✔
296
      , on_error_func_(global_on_error_func)
624✔
297
      , result_(0)
624✔
298
      , main_pool_notifier_()
624✔
299
      , main_pool_(main_pool_notifier_, "main_pool")
624✔
300
#ifdef HPX_HAVE_IO_POOL
301
      , io_pool_notifier_()
624✔
302
      , io_pool_(io_pool_notifier_, "io_pool")
624✔
303
#endif
304
#ifdef HPX_HAVE_TIMER_POOL
305
      , timer_pool_notifier_()
624✔
306
      , timer_pool_(timer_pool_notifier_, "timer_pool")
624✔
307
#endif
308
      , notifier_()
624✔
309
      , thread_manager_()
624✔
310
      , stop_called_(false)
624✔
311
      , stop_done_(false)
624✔
312
    {
624✔
313
        LPROGRESS_;
624✔
314

315
        // set notification policies only after the object was completely
316
        // initialized
317
        runtime::set_notification_policies(
624✔
318
            runtime::get_notification_policy(
624✔
319
                "worker-thread", runtime_local::os_thread_type::worker_thread),
320
#ifdef HPX_HAVE_IO_POOL
321
            runtime::get_notification_policy(
624✔
322
                "io-thread", runtime_local::os_thread_type::io_thread),
323
#endif
324
#ifdef HPX_HAVE_TIMER_POOL
325
            runtime::get_notification_policy(
624✔
326
                "timer-thread", runtime_local::os_thread_type::timer_thread),
327
#endif
328
            threads::detail::network_background_callback_type{});
624✔
329

330
        init_global_data();
624✔
331
        util::reinit_construct();
624✔
332

333
        if (initialize)
624✔
334
        {
335
            init();
624✔
336
        }
624✔
337
    }
624✔
338

339
    // this constructor is called by the distributed runtime only
340
    runtime::runtime(hpx::util::runtime_configuration& rtcfg)
2,368✔
341
      : rtcfg_(rtcfg)
592✔
342
      , instance_number_(++instance_number_counter_)
592✔
343
      , thread_support_(new util::thread_mapper)
592✔
344
      , topology_(resource::get_partitioner().get_topology())
592✔
345
      , state_(state::invalid)
592✔
346
      , on_start_func_(global_on_start_func)
592✔
347
      , on_stop_func_(global_on_stop_func)
592✔
348
      , on_error_func_(global_on_error_func)
592✔
349
      , result_(0)
592✔
350
      , main_pool_notifier_()
592✔
351
      , main_pool_(main_pool_notifier_, "main_pool")
592✔
352
#ifdef HPX_HAVE_IO_POOL
353
      , io_pool_notifier_()
592✔
354
      , io_pool_(io_pool_notifier_, "io_pool")
592✔
355
#endif
356
#ifdef HPX_HAVE_TIMER_POOL
357
      , timer_pool_notifier_()
592✔
358
      , timer_pool_(timer_pool_notifier_, "timer_pool")
592✔
359
#endif
360
      , notifier_()
592✔
361
      , thread_manager_()
592✔
362
      , stop_called_(false)
592✔
363
      , stop_done_(false)
592✔
364
    {
592✔
365
        init_global_data();
592✔
366
        util::reinit_construct();
592✔
367

368
        LPROGRESS_;
592✔
369
    }
592✔
370

371
    void runtime::set_notification_policies(notification_policy_type&& notifier,
1,216✔
372
#ifdef HPX_HAVE_IO_POOL
373
        notification_policy_type&& io_pool_notifier,
374
#endif
375
#ifdef HPX_HAVE_TIMER_POOL
376
        notification_policy_type&& timer_pool_notifier,
377
#endif
378
        threads::detail::network_background_callback_type
379
            network_background_callback)
380
    {
381
        notifier_ = HPX_MOVE(notifier);
1,216✔
382

383
        main_pool_.init(1);
1,216✔
384
#ifdef HPX_HAVE_IO_POOL
385
        io_pool_notifier_ = HPX_MOVE(io_pool_notifier);
1,216✔
386
        io_pool_.init(rtcfg_.get_thread_pool_size("io_pool"));
1,216✔
387
#endif
388
#ifdef HPX_HAVE_TIMER_POOL
389
        timer_pool_notifier_ = HPX_MOVE(timer_pool_notifier);
1,216✔
390
        timer_pool_.init(rtcfg_.get_thread_pool_size("timer_pool"));
1,216✔
391
#endif
392

393
        thread_manager_.reset(new hpx::threads::threadmanager(rtcfg_,
1,216✔
394
#ifdef HPX_HAVE_TIMER_POOL
395
            timer_pool_,
1,216✔
396
#endif
397
            notifier_, network_background_callback));
1,216✔
398
    }
1,216✔
399

400
    void runtime::init()
1,216✔
401
    {
402
        LPROGRESS_;
1,216✔
403

404
        try
405
        {
406
            // now create all threadmanager pools
407
            thread_manager_->create_pools();
1,216✔
408

409
            // this initializes the used_processing_units_ mask
410
            thread_manager_->init();
1,216✔
411

412
            // copy over all startup functions registered so far
413
            for (startup_function_type& f :
1,216✔
414
                detail::global_pre_startup_functions())
1,216✔
415
            {
416
                add_pre_startup_function(HPX_MOVE(f));
×
417
            }
418
            detail::global_pre_startup_functions().clear();
1,216✔
419

420
            for (startup_function_type& f : detail::global_startup_functions())
1,804✔
421
            {
422
                add_startup_function(HPX_MOVE(f));
588✔
423
            }
424
            detail::global_startup_functions().clear();
1,216✔
425

426
            for (shutdown_function_type& f :
1,216✔
427
                detail::global_pre_shutdown_functions())
1,216✔
428
            {
429
                add_pre_shutdown_function(HPX_MOVE(f));
×
430
            }
431
            detail::global_pre_shutdown_functions().clear();
1,216✔
432

433
            for (shutdown_function_type& f :
1,216✔
434
                detail::global_shutdown_functions())
1,216✔
435
            {
436
                add_shutdown_function(HPX_MOVE(f));
×
437
            }
438
            detail::global_shutdown_functions().clear();
1,216✔
439
        }
1,216✔
440
        catch (std::exception const& e)
441
        {
442
            // errors at this point need to be reported directly
443
            detail::report_exception_and_terminate(e);
×
444
        }
×
445
        catch (...)
446
        {
447
            // errors at this point need to be reported directly
448
            detail::report_exception_and_terminate(std::current_exception());
×
449
        }
×
450

451
        // set state to initialized
452
        set_state(state::initialized);
1,216✔
453
    }
1,216✔
454

455
    runtime::~runtime()
1,835✔
456
    {
1,835✔
457
        LRT_(debug).format("~runtime_local(entering)");
1,213✔
458

459
        // stop all services
460
        thread_manager_->stop();    // stops timer_pool_ as well
1,213✔
461
#ifdef HPX_HAVE_IO_POOL
462
        io_pool_.stop();
1,213✔
463
#endif
464
        LRT_(debug).format("~runtime_local(finished)");
1,213✔
465

466
        LPROGRESS_;
1,213✔
467

468
        // allow to reuse instance number if this was the only instance
469
        if (0 == instance_number_counter_)
1,213✔
470
            --instance_number_counter_;
1,213✔
471

472
        util::reinit_destruct();
1,213✔
473
        resource::detail::delete_partitioner();
1,213✔
474
    }
1,835✔
475

476
    void runtime::on_exit(hpx::function<void()> const& f)
×
477
    {
478
        std::lock_guard<std::mutex> l(mtx_);
×
479
        on_exit_functions_.push_back(f);
×
480
    }
×
481

482
    void runtime::starting()
1,216✔
483
    {
484
        state_.store(hpx::state::pre_main);
1,216✔
485
    }
1,216✔
486

487
    void runtime::stopping()
1,214✔
488
    {
489
        state_.store(hpx::state::stopped);
1,214✔
490

491
        using value_type = hpx::function<void()>;
492

493
        std::lock_guard<std::mutex> l(mtx_);
1,214✔
494
        for (value_type const& f : on_exit_functions_)
1,214✔
495
            f();
×
496
    }
1,214✔
497

498
    bool runtime::stopped() const
×
499
    {
500
        return state_.load() == hpx::state::stopped;
×
501
    }
502

503
    hpx::util::runtime_configuration& runtime::get_config()
1,652,558✔
504
    {
505
        return rtcfg_;
1,652,540✔
506
    }
507

508
    hpx::util::runtime_configuration const& runtime::get_config() const
67,863✔
509
    {
510
        return rtcfg_;
67,863✔
511
    }
512

513
    std::size_t runtime::get_instance_number() const
2✔
514
    {
515
        return static_cast<std::size_t>(instance_number_);
2✔
516
    }
517

518
    state runtime::get_state() const
93,707,946✔
519
    {
520
        return state_.load();
93,708,533✔
521
    }
522

523
    threads::topology const& runtime::get_topology() const
5✔
524
    {
525
        return topology_;
5✔
526
    }
527

528
    void runtime::set_state(state s)
6,878✔
529
    {
530
        LPROGRESS_ << get_runtime_state_name(s);
6,878✔
531
        state_.store(s);
6,878✔
532
    }
6,878✔
533

534
    ///////////////////////////////////////////////////////////////////////////
535
    std::atomic<int> runtime::instance_number_counter_(-1);
536

537
    ///////////////////////////////////////////////////////////////////////////
538
    namespace {
539
        std::uint64_t& runtime_uptime()
2,520✔
540
        {
541
            static std::uint64_t uptime = 0;
542
            return uptime;
2,520✔
543
        }
544
    }    // namespace
545

546
    void runtime::init_global_data()
1,216✔
547
    {
548
        runtime*& runtime_ = get_runtime_ptr();
1,216✔
549
        HPX_ASSERT(!runtime_);
1,216✔
550
        HPX_ASSERT(nullptr == threads::thread_self::get_self());
1,216✔
551

552
        runtime_ = this;
1,216✔
553
        runtime_uptime() = hpx::chrono::high_resolution_clock::now();
1,216✔
554
    }
1,216✔
555

556
    void runtime::deinit_global_data()
1,214✔
557
    {
558
        runtime*& runtime_ = get_runtime_ptr();
1,214✔
559
        HPX_ASSERT(runtime_);
1,214✔
560
        runtime_uptime() = 0;
1,214✔
561
        runtime_ = nullptr;
1,214✔
562
    }
1,214✔
563

564
    std::uint64_t runtime::get_system_uptime()
90✔
565
    {
566
        std::int64_t diff =
90✔
567
            hpx::chrono::high_resolution_clock::now() - runtime_uptime();
90✔
568
        return diff < 0LL ? 0ULL : static_cast<std::uint64_t>(diff);
90✔
569
    }
570

571
    threads::policies::callback_notifier::on_startstop_type
572
    runtime::on_start_func() const
×
573
    {
574
        return on_start_func_;
×
575
    }
576

577
    threads::policies::callback_notifier::on_startstop_type
578
    runtime::on_stop_func() const
×
579
    {
580
        return on_stop_func_;
×
581
    }
582

583
    threads::policies::callback_notifier::on_error_type runtime::on_error_func()
×
584
        const
585
    {
586
        return on_error_func_;
×
587
    }
588

589
    threads::policies::callback_notifier::on_startstop_type
590
    runtime::on_start_func(
×
591
        threads::policies::callback_notifier::on_startstop_type&& f)
592
    {
593
        threads::policies::callback_notifier::on_startstop_type newf =
×
594
            HPX_MOVE(f);
×
595
        std::swap(on_start_func_, newf);
×
596
        return newf;
×
597
    }
×
598

599
    threads::policies::callback_notifier::on_startstop_type
600
    runtime::on_stop_func(
×
601
        threads::policies::callback_notifier::on_startstop_type&& f)
602
    {
603
        threads::policies::callback_notifier::on_startstop_type newf =
×
604
            HPX_MOVE(f);
×
605
        std::swap(on_stop_func_, newf);
×
606
        return newf;
×
607
    }
×
608

609
    threads::policies::callback_notifier::on_error_type runtime::on_error_func(
×
610
        threads::policies::callback_notifier::on_error_type&& f)
611
    {
612
        threads::policies::callback_notifier::on_error_type newf = HPX_MOVE(f);
×
613
        std::swap(on_error_func_, newf);
×
614
        return newf;
×
615
    }
×
616

617
    std::uint32_t runtime::get_locality_id(error_code& /* ec */) const
25,538,887✔
618
    {
619
        return 0;
25,539,818✔
620
    }
621

622
    std::size_t runtime::get_num_worker_threads() const
1,129✔
623
    {
624
        HPX_ASSERT(thread_manager_);
1,129✔
625
        return thread_manager_->get_os_thread_count();
1,129✔
626
    }
627

628
    std::uint32_t runtime::get_num_localities(
1✔
629
        hpx::launch::sync_policy, error_code& /* ec */) const
630
    {
631
        return 1;
1✔
632
    }
633

634
    std::uint32_t runtime::get_initial_num_localities() const
×
635
    {
636
        return 1;
×
637
    }
638

639
    hpx::future<std::uint32_t> runtime::get_num_localities() const
×
640
    {
641
        return make_ready_future(std::uint32_t(1));
×
642
    }
643

644
    std::string runtime::get_locality_name() const
×
645
    {
646
        return "console";
×
647
    }
×
648

649
    ///////////////////////////////////////////////////////////////////////////
650
    threads::policies::callback_notifier::on_startstop_type
651
    get_thread_on_start_func()
×
652
    {
653
        runtime* rt = get_runtime_ptr();
×
654
        if (nullptr != rt)
×
655
        {
656
            return rt->on_start_func();
×
657
        }
658
        else
659
        {
660
            return global_on_start_func;
×
661
        }
662
    }
×
663

664
    threads::policies::callback_notifier::on_startstop_type
665
    get_thread_on_stop_func()
×
666
    {
667
        runtime* rt = get_runtime_ptr();
×
668
        if (nullptr != rt)
×
669
        {
670
            return rt->on_stop_func();
×
671
        }
672
        else
673
        {
674
            return global_on_stop_func;
×
675
        }
676
    }
×
677

678
    threads::policies::callback_notifier::on_error_type
679
    get_thread_on_error_func()
×
680
    {
681
        runtime* rt = get_runtime_ptr();
×
682
        if (nullptr != rt)
×
683
        {
684
            return rt->on_error_func();
×
685
        }
686
        else
687
        {
688
            return global_on_error_func;
×
689
        }
690
    }
×
691

692
    threads::policies::callback_notifier::on_startstop_type
693
    register_thread_on_start_func(
1✔
694
        threads::policies::callback_notifier::on_startstop_type&& f)
695
    {
696
        runtime* rt = get_runtime_ptr();
1✔
697
        if (nullptr != rt)
1✔
698
        {
699
            return rt->on_start_func(HPX_MOVE(f));
×
700
        }
701

702
        threads::policies::callback_notifier::on_startstop_type newf =
703
            HPX_MOVE(f);
1✔
704
        std::swap(global_on_start_func, newf);
1✔
705
        return newf;
1✔
706
    }
1✔
707

708
    threads::policies::callback_notifier::on_startstop_type
709
    register_thread_on_stop_func(
1✔
710
        threads::policies::callback_notifier::on_startstop_type&& f)
711
    {
712
        runtime* rt = get_runtime_ptr();
1✔
713
        if (nullptr != rt)
1✔
714
        {
715
            return rt->on_stop_func(HPX_MOVE(f));
×
716
        }
717

718
        threads::policies::callback_notifier::on_startstop_type newf =
719
            HPX_MOVE(f);
1✔
720
        std::swap(global_on_stop_func, newf);
1✔
721
        return newf;
1✔
722
    }
1✔
723

724
    threads::policies::callback_notifier::on_error_type
725
    register_thread_on_error_func(
1✔
726
        threads::policies::callback_notifier::on_error_type&& f)
727
    {
728
        runtime* rt = get_runtime_ptr();
1✔
729
        if (nullptr != rt)
1✔
730
        {
731
            return rt->on_error_func(HPX_MOVE(f));
×
732
        }
733

734
        threads::policies::callback_notifier::on_error_type newf = HPX_MOVE(f);
1✔
735
        std::swap(global_on_error_func, newf);
1✔
736
        return newf;
1✔
737
    }
1✔
738

739
    ///////////////////////////////////////////////////////////////////////////
740
    runtime& get_runtime()
1,791,350✔
741
    {
742
        HPX_ASSERT(get_runtime_ptr() != nullptr);
1,791,350✔
743
        return *get_runtime_ptr();
1,791,350✔
744
    }
745

746
    runtime*& get_runtime_ptr()
100,564,642✔
747
    {
748
        static runtime* runtime_ = nullptr;
749
        return runtime_;
100,564,642✔
750
    }
751

752
    std::string get_thread_name()
5✔
753
    {
754
        std::string& thread_name = detail::thread_name();
5✔
755
        if (thread_name.empty())
5✔
756
            return "<unknown>";
×
757
        return thread_name;
5✔
758
    }
5✔
759

760
    // Register the current kernel thread with HPX, this should be done once
761
    // for each external OS-thread intended to invoke HPX functionality.
762
    // Calling this function more than once will silently fail
763
    // (will return false).
764
    bool register_thread(runtime* rt, char const* name, error_code& ec)
4✔
765
    {
766
        HPX_ASSERT(rt);
4✔
767
        return rt->register_thread(name, 0, true, ec);
4✔
768
    }
769

770
    // Unregister the thread from HPX, this should be done once in
771
    // the end before the external thread exists.
772
    void unregister_thread(runtime* rt)
4✔
773
    {
774
        HPX_ASSERT(rt);
4✔
775
        rt->unregister_thread();
4✔
776
    }
4✔
777

778
    // Access data for a given OS thread that was previously registered by
779
    // \a register_thread. This function must be called from a thread that was
780
    // previously registered with the runtime.
781
    runtime_local::os_thread_data get_os_thread_data(std::string const& label)
×
782
    {
783
        return get_runtime().get_os_thread_data(label);
×
784
    }
785

786
    /// Enumerate all OS threads that have registered with the runtime.
787
    bool enumerate_os_threads(
4✔
788
        hpx::function<bool(os_thread_data const&)> const& f)
789
    {
790
        return get_runtime().enumerate_os_threads(f);
4✔
791
    }
792

793
    ///////////////////////////////////////////////////////////////////////////
794
    void report_error(std::size_t num_thread, std::exception_ptr const& e)
×
795
    {
796
        // Early and late exceptions
797
        if (!threads::threadmanager_is(hpx::state::running))
×
798
        {
799
            hpx::runtime* rt = hpx::get_runtime_ptr();
×
800
            if (rt)
×
801
                rt->report_error(num_thread, e);
×
802
            else
803
                detail::report_exception_and_terminate(e);
×
804
            return;
×
805
        }
806

807
        get_runtime().get_thread_manager().report_error(num_thread, e);
×
808
    }
×
809

810
    void report_error(std::exception_ptr const& e)
×
811
    {
812
        // Early and late exceptions
813
        if (!threads::threadmanager_is(hpx::state::running))
×
814
        {
815
            hpx::runtime* rt = hpx::get_runtime_ptr();
×
816
            if (rt)
×
817
                rt->report_error(std::size_t(-1), e);
×
818
            else
819
                detail::report_exception_and_terminate(e);
×
820
            return;
×
821
        }
822

823
        std::size_t num_thread = hpx::get_worker_thread_num();
×
824
        get_runtime().get_thread_manager().report_error(num_thread, e);
×
825
    }
×
826

827
    bool register_on_exit(hpx::function<void()> const& f)
×
828
    {
829
        runtime* rt = get_runtime_ptr();
×
830
        if (nullptr == rt)
×
831
            return false;
×
832

833
        rt->on_exit(f);
×
834
        return true;
×
835
    }
×
836

837
    std::size_t get_runtime_instance_number()
×
838
    {
839
        runtime* rt = get_runtime_ptr();
×
840
        return (nullptr == rt) ? 0 : rt->get_instance_number();
×
841
    }
842

843
    ///////////////////////////////////////////////////////////////////////////
844
    std::string get_config_entry(
9,649✔
845
        std::string const& key, std::string const& dflt)
846
    {
847
        if (get_runtime_ptr() != nullptr)
9,649✔
848
        {
849
            return get_runtime().get_config().get_entry(key, dflt);
5,992✔
850
        }
851

852
        return dflt;
3,657✔
853
    }
9,649✔
854

855
    std::string get_config_entry(std::string const& key, std::size_t dflt)
23,757✔
856
    {
857
        if (get_runtime_ptr() != nullptr)
23,757✔
858
        {
859
            return get_runtime().get_config().get_entry(key, dflt);
21,319✔
860
        }
861

862
        return std::to_string(dflt);
2,438✔
863
    }
23,757✔
864

865
    // set entries
866
    void set_config_entry(std::string const& key, std::string const& value)
4✔
867
    {
868
        if (get_runtime_ptr() != nullptr)
4✔
869
        {
870
            get_runtime_ptr()->get_config().add_entry(key, value);
4✔
871
            return;
4✔
872
        }
873
    }
4✔
874

875
    void set_config_entry(std::string const& key, std::size_t value)
×
876
    {
877
        set_config_entry(key, std::to_string(value));
×
878
    }
×
879

880
    void set_config_entry_callback(std::string const& key,
570✔
881
        hpx::function<void(std::string const&, std::string const&)> const&
882
            callback)
883
    {
884
        if (get_runtime_ptr() != nullptr)
570✔
885
        {
886
            get_runtime_ptr()->get_config().add_notification_callback(
1,140✔
887
                key, callback);
570✔
888
            return;
570✔
889
        }
890
    }
570✔
891

892
    namespace util {
893
        ///////////////////////////////////////////////////////////////////////////
894
        // retrieve the command line arguments for the current locality
895
        bool retrieve_commandline_arguments(
1✔
896
            hpx::program_options::options_description const& app_options,
897
            hpx::program_options::variables_map& vm)
898
        {
899
            // The command line for this application instance is available from
900
            // this configuration section:
901
            //
902
            //     [hpx]
903
            //     cmd_line=....
904
            //
905
            std::string cmdline;
1✔
906

907
            hpx::util::section& cfg = hpx::get_runtime().get_config();
1✔
908
            if (cfg.has_entry("hpx.cmd_line"))
1✔
909
                cmdline = cfg.get_entry("hpx.cmd_line");
1✔
910

911
            return hpx::local::detail::parse_commandline(
1✔
912
                cfg, app_options, cmdline, vm, allow_unregistered);
1✔
913
        }
1✔
914

915
        ///////////////////////////////////////////////////////////////////////////
916
        // retrieve the command line arguments for the current locality
917
        bool retrieve_commandline_arguments(
×
918
            std::string const& appname, hpx::program_options::variables_map& vm)
919
        {
920
            using hpx::program_options::options_description;
921

922
            options_description desc_commandline(
×
923
                "Usage: " + appname + " [options]");
×
924

925
            return retrieve_commandline_arguments(desc_commandline, vm);
×
926
        }
×
927
    }    // namespace util
928

929
    ///////////////////////////////////////////////////////////////////////////
930
    std::size_t get_os_thread_count()
1,453✔
931
    {
932
        runtime* rt = get_runtime_ptr();
1,453✔
933
        if (nullptr == rt)
1,453✔
934
        {
935
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
936
                "hpx::get_os_thread_count()",
937
                "the runtime system has not been initialized yet");
938
            return std::size_t(0);
939
        }
940
        return rt->get_config().get_os_thread_count();
1,453✔
941
    }
×
942

943
    bool is_scheduler_numa_sensitive()
×
944
    {
945
        runtime* rt = get_runtime_ptr();
×
946
        if (nullptr == rt)
×
947
        {
948
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
949
                "hpx::is_scheduler_numa_sensitive",
950
                "the runtime system has not been initialized yet");
951
            return false;
952
        }
953

954
        if (std::size_t(-1) != get_worker_thread_num())
×
955
            return false;
×
956
        return false;
×
957
    }
×
958

959
    ///////////////////////////////////////////////////////////////////////////
960
    bool is_running()
1,093✔
961
    {
962
        runtime* rt = get_runtime_ptr();
1,093✔
963
        if (nullptr != rt)
1,093✔
964
            return rt->get_state() == hpx::state::running;
1,093✔
965
        return false;
×
966
    }
1,093✔
967

968
    bool is_stopped()
2,741✔
969
    {
970
        if (!detail::exit_called)
2,741✔
971
        {
972
            runtime* rt = get_runtime_ptr();
2,741✔
973
            if (nullptr != rt)
2,741✔
974
                return rt->get_state() == hpx::state::stopped;
2,741✔
975
        }
×
976
        return true;    // assume stopped
×
977
    }
2,741✔
978

979
    bool is_stopped_or_shutting_down()
457,330✔
980
    {
981
        runtime* rt = get_runtime_ptr();
457,330✔
982
        if (!detail::exit_called && nullptr != rt)
457,330✔
983
        {
984
            state st = rt->get_state();
457,329✔
985
            return st >= hpx::state::shutdown;
457,329✔
986
        }
987
        return true;    // assume stopped
×
988
    }
457,329✔
989

990
    bool tolerate_node_faults()
×
991
    {
992
#ifdef HPX_HAVE_FAULT_TOLERANCE
993
        return true;
994
#else
995
        return false;
×
996
#endif
997
    }
998

999
    bool is_starting()
184,541✔
1000
    {
1001
        runtime* rt = get_runtime_ptr();
184,541✔
1002
        return nullptr != rt ? rt->get_state() <= hpx::state::startup : true;
184,541✔
1003
    }
1004

1005
    bool is_pre_startup()
×
1006
    {
1007
        runtime* rt = get_runtime_ptr();
×
1008
        return nullptr != rt ? rt->get_state() < hpx::state::startup : true;
×
1009
    }
1010
}    // namespace hpx
1011

1012
///////////////////////////////////////////////////////////////////////////////
1013
namespace hpx { namespace util {
1014
    std::string expand(std::string const& in)
×
1015
    {
1016
        return get_runtime().get_config().expand(in);
×
1017
    }
1018

1019
    void expand(std::string& in)
1✔
1020
    {
1021
        get_runtime().get_config().expand(in, std::string::size_type(-1));
1✔
1022
    }
1✔
1023
}}    // namespace hpx::util
1024

1025
///////////////////////////////////////////////////////////////////////////////
1026
namespace hpx { namespace threads {
1027
    threadmanager& get_thread_manager()
50,606✔
1028
    {
1029
        return get_runtime().get_thread_manager();
50,606✔
1030
    }
1031

1032
    // shortcut for runtime_configuration::get_default_stack_size
1033
    std::ptrdiff_t get_default_stack_size()
×
1034
    {
1035
        return get_runtime().get_config().get_default_stack_size();
×
1036
    }
1037

1038
    // shortcut for runtime_configuration::get_stack_size
1039
    std::ptrdiff_t get_stack_size(threads::thread_stacksize stacksize)
1,592,985✔
1040
    {
1041
        if (stacksize == threads::thread_stacksize::current)
1,592,986✔
1042
            return threads::get_self_stacksize();
×
1043

1044
        return get_runtime().get_config().get_stack_size(stacksize);
1,592,987✔
1045
    }
1,592,987✔
1046

1047
    void reset_thread_distribution()
×
1048
    {
1049
        get_runtime().get_thread_manager().reset_thread_distribution();
×
1050
    }
×
1051

1052
    void set_scheduler_mode(threads::policies::scheduler_mode m)
×
1053
    {
1054
        get_runtime().get_thread_manager().set_scheduler_mode(m);
×
1055
    }
×
1056

1057
    void add_scheduler_mode(threads::policies::scheduler_mode m)
1✔
1058
    {
1059
        get_runtime().get_thread_manager().add_scheduler_mode(m);
1✔
1060
    }
1✔
1061

1062
    void add_remove_scheduler_mode(
×
1063
        threads::policies::scheduler_mode to_add_mode,
1064
        threads::policies::scheduler_mode to_remove_mode)
1065
    {
1066
        get_runtime().get_thread_manager().add_remove_scheduler_mode(
×
1067
            to_add_mode, to_remove_mode);
×
1068
    }
×
1069

1070
    void remove_scheduler_mode(threads::policies::scheduler_mode m)
1✔
1071
    {
1072
        get_runtime().get_thread_manager().remove_scheduler_mode(m);
1✔
1073
    }
1✔
1074

1075
    topology const& get_topology()
2✔
1076
    {
1077
        hpx::runtime* rt = hpx::get_runtime_ptr();
2✔
1078
        if (rt == nullptr)
2✔
1079
        {
1080
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1081
                "hpx::threads::get_topology",
1082
                "the hpx runtime system has not been initialized yet");
1083
        }
1084
        return rt->get_topology();
2✔
1085
    }
×
1086
}}    // namespace hpx::threads
1087

1088
///////////////////////////////////////////////////////////////////////////////
1089
namespace hpx {
1090
    std::uint64_t get_system_uptime()
90✔
1091
    {
1092
        return runtime::get_system_uptime();
90✔
1093
    }
1094

1095
    hpx::util::runtime_configuration const& get_config()
16,821✔
1096
    {
1097
        return get_runtime().get_config();
16,821✔
1098
    }
1099

1100
    hpx::util::io_service_pool* get_thread_pool(
17,654✔
1101
        char const* name, char const* name_suffix)
1102
    {
1103
        std::string full_name(name);
17,654✔
1104
        full_name += name_suffix;
17,654✔
1105
        return get_runtime().get_thread_pool(full_name.c_str());
17,654✔
1106
    }
17,654✔
1107

1108
    ///////////////////////////////////////////////////////////////////////////
1109
    /// Return true if networking is enabled.
1110
    bool is_networking_enabled()
2,237✔
1111
    {
1112
        runtime* rt = get_runtime_ptr();
2,237✔
1113
        if (nullptr != rt)
2,237✔
1114
        {
1115
            return rt->is_networking_enabled();
1,186✔
1116
        }
1117
        return true;    // be on the safe side, enable networking
1,051✔
1118
    }
2,237✔
1119
}    // namespace hpx
1120

1121
#if defined(_WIN64) && defined(HPX_DEBUG) &&                                   \
1122
    !defined(HPX_HAVE_FIBER_BASED_COROUTINES)
1123
#include <io.h>
1124
#endif
1125

1126
namespace hpx {
1127
    namespace detail {
1128
        ///////////////////////////////////////////////////////////////////////
1129
        // There is no need to protect these global from thread concurrent
1130
        // access as they are access during early startup only.
1131
        std::list<startup_function_type>& global_pre_startup_functions()
2,432✔
1132
        {
1133
            static std::list<startup_function_type>
2,432✔
1134
                global_pre_startup_functions_;
1,050✔
1135
            return global_pre_startup_functions_;
2,432✔
1136
        }
1137

1138
        std::list<startup_function_type>& global_startup_functions()
3,020✔
1139
        {
1140
            static std::list<startup_function_type> global_startup_functions_;
3,020✔
1141
            return global_startup_functions_;
3,020✔
1142
        }
1143

1144
        std::list<shutdown_function_type>& global_pre_shutdown_functions()
2,432✔
1145
        {
1146
            static std::list<shutdown_function_type>
2,432✔
1147
                global_pre_shutdown_functions_;
1,050✔
1148
            return global_pre_shutdown_functions_;
2,432✔
1149
        }
1150

1151
        std::list<shutdown_function_type>& global_shutdown_functions()
2,432✔
1152
        {
1153
            static std::list<shutdown_function_type> global_shutdown_functions_;
2,432✔
1154
            return global_shutdown_functions_;
2,432✔
1155
        }
1156
    }    // namespace detail
1157

1158
    ///////////////////////////////////////////////////////////////////////////
1159
    void register_pre_startup_function(startup_function_type f)
×
1160
    {
1161
        runtime* rt = get_runtime_ptr();
×
1162
        if (nullptr != rt)
×
1163
        {
1164
            if (rt->get_state() > hpx::state::pre_startup)
×
1165
            {
1166
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1167
                    "register_pre_startup_function",
1168
                    "Too late to register a new pre-startup function.");
1169
                return;
1170
            }
1171
            rt->add_pre_startup_function(HPX_MOVE(f));
×
1172
        }
×
1173
        else
1174
        {
1175
            detail::global_pre_startup_functions().push_back(HPX_MOVE(f));
×
1176
        }
1177
    }
×
1178

1179
    void register_startup_function(startup_function_type f)
588✔
1180
    {
1181
        runtime* rt = get_runtime_ptr();
588✔
1182
        if (nullptr != rt)
588✔
1183
        {
1184
            if (rt->get_state() > hpx::state::startup)
×
1185
            {
1186
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1187
                    "register_startup_function",
1188
                    "Too late to register a new startup function.");
1189
                return;
1190
            }
1191
            rt->add_startup_function(HPX_MOVE(f));
×
1192
        }
×
1193
        else
1194
        {
1195
            detail::global_startup_functions().push_back(HPX_MOVE(f));
588✔
1196
        }
1197
    }
588✔
1198

1199
    void register_pre_shutdown_function(shutdown_function_type f)
594✔
1200
    {
1201
        runtime* rt = get_runtime_ptr();
594✔
1202
        if (nullptr != rt)
594✔
1203
        {
1204
            if (rt->get_state() > hpx::state::pre_shutdown)
594✔
1205
            {
1206
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1207
                    "register_pre_shutdown_function",
1208
                    "Too late to register a new pre-shutdown function.");
1209
                return;
1210
            }
1211
            rt->add_pre_shutdown_function(HPX_MOVE(f));
594✔
1212
        }
594✔
1213
        else
1214
        {
1215
            detail::global_pre_shutdown_functions().push_back(HPX_MOVE(f));
×
1216
        }
1217
    }
594✔
1218

1219
    void register_shutdown_function(shutdown_function_type f)
595✔
1220
    {
1221
        runtime* rt = get_runtime_ptr();
595✔
1222
        if (nullptr != rt)
595✔
1223
        {
1224
            if (rt->get_state() > hpx::state::shutdown)
595✔
1225
            {
1226
                HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1227
                    "register_shutdown_function",
1228
                    "Too late to register a new shutdown function.");
1229
                return;
1230
            }
1231
            rt->add_shutdown_function(HPX_MOVE(f));
595✔
1232
        }
595✔
1233
        else
1234
        {
1235
            detail::global_shutdown_functions().push_back(HPX_MOVE(f));
×
1236
        }
1237
    }
595✔
1238

1239
    void runtime::call_startup_functions(bool pre_startup)
1,246✔
1240
    {
1241
        if (pre_startup)
1,246✔
1242
        {
1243
            set_state(hpx::state::pre_startup);
623✔
1244
            for (startup_function_type& f : pre_startup_functions_)
623✔
1245
            {
1246
                f();
×
1247
            }
1248
        }
623✔
1249
        else
1250
        {
1251
            set_state(hpx::state::startup);
623✔
1252
            for (startup_function_type& f : startup_functions_)
627✔
1253
            {
1254
                f();
4✔
1255
            }
1256
        }
1257
    }
1,246✔
1258

1259
    namespace detail {
1260
        void handle_print_bind(std::size_t num_threads)
×
1261
        {
1262
            threads::topology& top = threads::create_topology();
×
1263
            auto const& rp = hpx::resource::get_partitioner();
×
1264
            auto const& tm = get_runtime().get_thread_manager();
×
1265

1266
            {
1267
                // make sure all output is kept together
1268
                std::ostringstream strm;
×
1269

1270
                strm << std::string(79, '*') << '\n';
×
1271
                strm << "locality: " << hpx::get_locality_id() << '\n';
×
1272
                for (std::size_t i = 0; i != num_threads; ++i)
×
1273
                {
1274
                    // print the mask for the current PU
1275
                    threads::mask_cref_type pu_mask = rp.get_pu_mask(i);
×
1276

1277
                    if (!threads::any(pu_mask))
×
1278
                    {
1279
                        strm << std::setw(4) << i    //-V112
×
1280
                             << ": thread binding disabled" << std::endl;
×
1281
                    }
×
1282
                    else
1283
                    {
1284
                        std::string pool_name = tm.get_pool(i).get_pool_name();
×
1285
                        top.print_affinity_mask(strm, i, pu_mask, pool_name);
×
1286
                    }
×
1287

1288
                    // Make sure the mask does not contradict the CPU bindings
1289
                    // returned by the system (see #973: Would like option to
1290
                    // report HWLOC bindings).
1291
                    error_code ec(throwmode::lightweight);
×
1292
                    std::thread& blob = tm.get_os_thread_handle(i);
×
1293
                    threads::mask_type boundcpu =
1294
                        top.get_cpubind_mask(blob, ec);
×
1295

1296
                    // The masks reported by HPX must be the same as the ones
1297
                    // reported from HWLOC.
1298
                    if (!ec && threads::any(boundcpu) &&
×
1299
                        !threads::equal(boundcpu, pu_mask, num_threads))
×
1300
                    {
1301
                        std::string boundcpu_str = threads::to_string(boundcpu);
×
1302
                        std::string pu_mask_str = threads::to_string(pu_mask);
×
1303
                        HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
1304
                            "handle_print_bind",
1305
                            hpx::util::format(
1306
                                "unexpected mismatch between locality {1}: "
1307
                                "binding reported from HWLOC({2}) and HPX({3}) "
1308
                                "on thread {4}",
1309
                                hpx::get_locality_id(), boundcpu_str,
1310
                                pu_mask_str, i));
1311
                    }
×
1312
                }
×
1313

1314
                std::cout << strm.str();
×
1315
            }
×
1316
        }
×
1317
    }    // namespace detail
1318

1319
    threads::thread_result_type runtime::run_helper(
1,216✔
1320
        hpx::function<runtime::hpx_main_function_type> const& func, int& result,
1321
        bool call_startup)
1322
    {
1323
        bool caught_exception = false;
1,216✔
1324
        try
1325
        {
1326
            {
1327
                hpx::program_options::options_description options;
1,216✔
1328
                result = hpx::local::detail::handle_late_commandline_options(
1,216✔
1329
                    get_config(), options, &detail::handle_print_bind);
1,216✔
1330
                if (result)
1,216✔
1331
                {
1332
                    lbt_ << "runtime_local::run_helper: bootstrap "
1✔
1333
                            "aborted, bailing out";
1334

1335
                    set_state(hpx::state::running);
1✔
1336
                    finalize(-1.0);
1✔
1337

1338
                    return threads::thread_result_type(
1✔
1339
                        threads::thread_schedule_state::terminated,
1✔
1340
                        threads::invalid_thread_id);
1341
                }
1342
            }
1,216✔
1343

1344
            if (call_startup)
1,215✔
1345
            {
1346
                call_startup_functions(true);
623✔
1347
                lbt_ << "(3rd stage) run_helper: ran pre-startup functions";
623✔
1348

1349
                call_startup_functions(false);
623✔
1350
                lbt_ << "(4th stage) run_helper: ran startup functions";
623✔
1351
            }
623✔
1352

1353
            lbt_ << "(4th stage) runtime::run_helper: bootstrap complete";
1,215✔
1354
            set_state(hpx::state::running);
1,215✔
1355

1356
            // Now, execute the user supplied thread function (hpx_main)
1357
            if (!!func)
1,215✔
1358
            {
1359
                lbt_ << "(last stage) runtime::run_helper: about to "
1,082✔
1360
                        "invoke hpx_main";
1361

1362
                // Change our thread description, as we're about to call hpx_main
1363
                threads::set_thread_description(
1,082✔
1364
                    threads::get_self_id(), "hpx_main");
1,082✔
1365

1366
                // Call hpx_main
1367
                result = func();
1,082✔
1368
            }
1,073✔
1369
        }
1,213✔
1370
        catch (...)
1371
        {
1372
            // make sure exceptions thrown in hpx_main don't escape
1373
            // unnoticed
1374
            {
1375
                std::lock_guard<std::mutex> l(mtx_);
7✔
1376
                exception_ = std::current_exception();
7✔
1377
            }
7✔
1378
            result = -1;
7✔
1379
            caught_exception = true;
7✔
1380
        }
7✔
1381

1382
        if (caught_exception)
1,213✔
1383
        {
1384
            HPX_ASSERT(exception_);
7✔
1385
            report_error(exception_, false);
7✔
1386
            finalize(-1.0);    // make sure the application exits
7✔
1387
        }
7✔
1388

1389
        return threads::thread_result_type(
1,213✔
1390
            threads::thread_schedule_state::terminated,
1,213✔
1391
            threads::invalid_thread_id);
1392
    }
1,221✔
1393

1394
    int runtime::start(
624✔
1395
        hpx::function<hpx_main_function_type> const& func, bool blocking)
1396
    {
1397
#if defined(_WIN64) && defined(HPX_DEBUG) &&                                   \
1398
    !defined(HPX_HAVE_FIBER_BASED_COROUTINES)
1399
        // needs to be called to avoid problems at system startup
1400
        // see: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100319
1401
        _isatty(0);
1402
#endif
1403
        // {{{ early startup code - local
1404

1405
        // initialize instrumentation system
1406
#ifdef HPX_HAVE_APEX
1407
        util::external_timer::init(nullptr, 0, 1);
1408
#endif
1409

1410
        LRT_(info).format("cmd_line: {}", get_config().get_cmd_line());
624✔
1411

1412
        lbt_ << "(1st stage) runtime::start: booting locality " << here();
624✔
1413

1414
        // Register this thread with the runtime system to allow calling
1415
        // certain HPX functionality from the main thread. Also calls
1416
        // registered startup callbacks.
1417
        init_tss_helper("main-thread",
624✔
1418
            runtime_local::os_thread_type::main_thread, 0, 0, "", "", false);
1419

1420
#ifdef HPX_HAVE_IO_POOL
1421
        // start the io pool
1422
        io_pool_.run(false);
624✔
1423
        lbt_ << "(1st stage) runtime::start: started the application "
624✔
1424
                "I/O service pool";
1425
#endif
1426
        // start the thread manager
1427
        thread_manager_->run();
624✔
1428
        lbt_ << "(1st stage) runtime::start: started threadmanager";
624✔
1429
        // }}}
1430

1431
        // {{{ launch main
1432
        // register the given main function with the thread manager
1433
        lbt_ << "(1st stage) runtime::start: launching run_helper "
624✔
1434
                "HPX thread";
1435

1436
        threads::thread_init_data data(hpx::bind(&runtime::run_helper, this,
1,872✔
1437
                                           func, std::ref(result_), true),
624✔
1438
            "run_helper", threads::thread_priority::normal,
624✔
1439
            threads::thread_schedule_hint(0), threads::thread_stacksize::large);
624✔
1440

1441
        this->runtime::starting();
624✔
1442
        threads::thread_id_ref_type id = threads::invalid_thread_id;
624✔
1443
        thread_manager_->register_thread(data, id);
624✔
1444
        // }}}
1445

1446
        // block if required
1447
        if (blocking)
624✔
1448
        {
1449
            return wait();    // wait for the shutdown_action to be executed
×
1450
        }
1451
        else
1452
        {
1453
            // wait for at least hpx::state::running
1454
            util::yield_while(
624✔
1455
                [this]() { return get_state() < hpx::state::running; },
73,939✔
1456
                "runtime::start");
1457
        }
1458

1459
        return 0;    // return zero as we don't know the outcome of hpx_main yet
624✔
1460
    }
624✔
1461

1462
    int runtime::start(bool blocking)
16✔
1463
    {
1464
        hpx::function<hpx_main_function_type> empty_main;
16✔
1465
        return start(empty_main, blocking);
16✔
1466
    }
16✔
1467

1468
    ///////////////////////////////////////////////////////////////////////////
1469
    void runtime::notify_finalize()
622✔
1470
    {
1471
        std::unique_lock<std::mutex> l(mtx_);
622✔
1472
        if (!stop_called_)
622✔
1473
        {
1474
            stop_called_ = true;
622✔
1475
            stop_done_ = true;
622✔
1476
            wait_condition_.notify_all();
622✔
1477
        }
622✔
1478
    }
622✔
1479

1480
    void runtime::wait_finalize()
624✔
1481
    {
1482
        std::unique_lock<std::mutex> l(mtx_);
624✔
1483
        while (!stop_done_)
1,198✔
1484
        {
1485
            LRT_(info).format("runtime: about to enter wait state");
576✔
1486
            wait_condition_.wait(l);
574✔
1487
            LRT_(info).format("runtime: exiting wait state");
576✔
1488
        }
1489
    }
622✔
1490

1491
    void runtime::wait_helper(
624✔
1492
        std::mutex& mtx, std::condition_variable& cond, bool& running)
1493
    {
1494
        // signal successful initialization
1495
        {
1496
            std::lock_guard<std::mutex> lk(mtx);
624✔
1497
            running = true;
624✔
1498
            cond.notify_all();
624✔
1499
        }
624✔
1500

1501
        // register this thread with any possibly active Intel tool
1502
        std::string thread_name("main-thread#wait_helper");
624✔
1503
        HPX_ITT_THREAD_SET_NAME(thread_name.c_str());
622✔
1504

1505
        // set thread name as shown in Visual Studio
1506
        util::set_thread_name(thread_name.c_str());
622✔
1507

1508
#if defined(HPX_HAVE_APEX)
1509
        // not registering helper threads - for now
1510
        //util::external_timer::register_thread(thread_name.c_str());
1511
#endif
1512

1513
        wait_finalize();
622✔
1514

1515
        // stop main thread pool
1516
        main_pool_.stop();
622✔
1517
    }
622✔
1518

1519
    int runtime::wait()
624✔
1520
    {
1521
        LRT_(info).format("runtime_local: about to enter wait state");
624✔
1522

1523
        // start the wait_helper in a separate thread
1524
        std::mutex mtx;
624✔
1525
        std::condition_variable cond;
624✔
1526
        bool running = false;
624✔
1527

1528
        std::thread t(hpx::bind(&runtime::wait_helper, this, std::ref(mtx),
1,248✔
1529
            std::ref(cond), std::ref(running)));
624✔
1530

1531
        // wait for the thread to run
1532
        {
1533
            std::unique_lock<std::mutex> lk(mtx);
624✔
1534
            // NOLINTNEXTLINE(bugprone-infinite-loop)
1535
            while (!running)    // -V776 // -V1044
1,248✔
1536
                cond.wait(lk);
624✔
1537
        }
622✔
1538

1539
        // use main thread to drive main thread pool
1540
        main_pool_.thread_run(0);
622✔
1541

1542
        // block main thread
1543
        t.join();
622✔
1544

1545
        thread_manager_->wait();
622✔
1546

1547
        LRT_(info).format("runtime_local: exiting wait state");
622✔
1548
        return result_;
622✔
1549
    }
622✔
1550

1551
    ///////////////////////////////////////////////////////////////////////////
1552
    // First half of termination process: stop thread manager,
1553
    // schedule a task managed by timer_pool to initiate second part
1554
    void runtime::stop(bool blocking)
622✔
1555
    {
1556
        LRT_(warning).format("runtime_local: about to stop services");
622✔
1557

1558
        // execute all on_exit functions whenever the first thread calls this
1559
        this->runtime::stopping();
622✔
1560

1561
        // stop runtime_local services (threads)
1562
        thread_manager_->stop(false);    // just initiate shutdown
622✔
1563

1564
#ifdef HPX_HAVE_APEX
1565
        util::external_timer::finalize();
1566
#endif
1567

1568
        if (threads::get_self_ptr())
622✔
1569
        {
1570
            // schedule task on separate thread to execute stop_helper() below
1571
            // this is necessary as this function (stop()) might have been called
1572
            // from a HPX thread, so it would deadlock by waiting for the thread
1573
            // manager
1574
            std::mutex mtx;
×
1575
            std::condition_variable cond;
×
1576
            std::unique_lock<std::mutex> l(mtx);
×
1577

1578
            std::thread t(hpx::bind(&runtime::stop_helper, this, blocking,
×
1579
                std::ref(cond), std::ref(mtx)));
×
1580
            cond.wait(l);
×
1581

1582
            t.join();
×
1583
        }
×
1584
        else
1585
        {
1586
            thread_manager_->stop(blocking);    // wait for thread manager
622✔
1587

1588
            deinit_global_data();
622✔
1589

1590
            // this disables all logging from the main thread
1591
            deinit_tss_helper("main-thread", 0);
622✔
1592

1593
            LRT_(info).format("runtime_local: stopped all services");
622✔
1594
        }
1595

1596
#ifdef HPX_HAVE_TIMER_POOL
1597
        LTM_(info).format("stop: stopping timer pool");
622✔
1598
        timer_pool_.stop();
622✔
1599
        if (blocking)
622✔
1600
        {
1601
            timer_pool_.join();
622✔
1602
            timer_pool_.clear();
622✔
1603
        }
622✔
1604
#endif
1605
#ifdef HPX_HAVE_IO_POOL
1606
        LTM_(info).format("stop: stopping io pool");
622✔
1607
        io_pool_.stop();
622✔
1608
        if (blocking)
622✔
1609
        {
1610
            io_pool_.join();
622✔
1611
            io_pool_.clear();
622✔
1612
        }
622✔
1613
#endif
1614
    }
622✔
1615

1616
    // Second step in termination: shut down all services.
1617
    // This gets executed as a task in the timer_pool io_service and not as
1618
    // a HPX thread!
1619
    void runtime::stop_helper(
×
1620
        bool blocking, std::condition_variable& cond, std::mutex& mtx)
1621
    {
1622
        // wait for thread manager to exit
1623
        thread_manager_->stop(blocking);    // wait for thread manager
×
1624

1625
        deinit_global_data();
×
1626

1627
        // this disables all logging from the main thread
1628
        deinit_tss_helper("main-thread", 0);
×
1629

1630
        LRT_(info).format("runtime_local: stopped all services");
×
1631

1632
        std::lock_guard<std::mutex> l(mtx);
×
1633
        cond.notify_all();    // we're done now
×
1634
    }
×
1635

1636
    int runtime::suspend()
119✔
1637
    {
1638
        LRT_(info).format("runtime_local: about to suspend runtime");
119✔
1639

1640
        if (state_.load() == hpx::state::sleeping)
119✔
1641
        {
1642
            return 0;
×
1643
        }
1644

1645
        if (state_.load() != hpx::state::running)
119✔
1646
        {
1647
            HPX_THROW_EXCEPTION(hpx::error::invalid_status, "runtime::suspend",
×
1648
                "Can only suspend runtime from running state");
1649
            return -1;
1650
        }
1651

1652
        thread_manager_->suspend();
119✔
1653

1654
#ifdef HPX_HAVE_TIMER_POOL
1655
        timer_pool_.wait();
119✔
1656
#endif
1657
#ifdef HPX_HAVE_IO_POOL
1658
        io_pool_.wait();
119✔
1659
#endif
1660

1661
        set_state(hpx::state::sleeping);
119✔
1662

1663
        return 0;
119✔
1664
    }
119✔
1665

1666
    int runtime::resume()
119✔
1667
    {
1668
        LRT_(info).format("runtime_local: about to resume runtime");
119✔
1669

1670
        if (state_.load() == hpx::state::running)
119✔
1671
        {
1672
            return 0;
×
1673
        }
1674

1675
        if (state_.load() != hpx::state::sleeping)
119✔
1676
        {
1677
            HPX_THROW_EXCEPTION(hpx::error::invalid_status, "runtime::resume",
×
1678
                "Can only resume runtime from suspended state");
1679
            return -1;
1680
        }
1681

1682
        thread_manager_->resume();
119✔
1683

1684
        set_state(hpx::state::running);
119✔
1685

1686
        return 0;
119✔
1687
    }
119✔
1688

1689
    int runtime::finalize(double /*shutdown_timeout*/)
622✔
1690
    {
1691
        notify_finalize();
622✔
1692
        return 0;
622✔
1693
    }
1694

1695
    bool runtime::is_networking_enabled()
×
1696
    {
1697
        return false;
×
1698
    }
1699

1700
    hpx::threads::threadmanager& runtime::get_thread_manager()
371,925✔
1701
    {
1702
        return *thread_manager_;
371,925✔
1703
    }
1704

1705
    std::string runtime::here() const
1,573✔
1706
    {
1707
        return "127.0.0.1";
1,573✔
1708
    }
×
1709

1710
    ///////////////////////////////////////////////////////////////////////////
1711
    bool runtime::report_error(std::size_t num_thread,
5✔
1712
        std::exception_ptr const& e, bool /*terminate_all*/)
1713
    {
1714
        // call thread-specific user-supplied on_error handler
1715
        bool report_exception = true;
5✔
1716
        if (on_error_func_)
5✔
1717
        {
1718
            report_exception = on_error_func_(num_thread, e);
1✔
1719
        }
1✔
1720

1721
        // Early and late exceptions, errors outside of HPX-threads
1722
        if (!threads::get_self_ptr() ||
5✔
1723
            !threads::threadmanager_is(hpx::state::running))
5✔
1724
        {
1725
            // report the error to the local console
1726
            if (report_exception)
×
1727
            {
1728
                detail::report_exception_and_continue(e);
×
1729
            }
×
1730

1731
            // store the exception to be able to rethrow it later
1732
            {
1733
                std::lock_guard<std::mutex> l(mtx_);
×
1734
                exception_ = e;
×
1735
            }
×
1736

1737
            notify_finalize();
×
1738
            stop(false);
×
1739

1740
            return report_exception;
×
1741
        }
1742

1743
        return report_exception;
5✔
1744
    }
5✔
1745

1746
    bool runtime::report_error(std::exception_ptr const& e, bool terminate_all)
5✔
1747
    {
1748
        return report_error(hpx::get_worker_thread_num(), e, terminate_all);
5✔
1749
    }
1750

1751
    void runtime::rethrow_exception()
1,214✔
1752
    {
1753
        if (state_.load() > hpx::state::running)
1,214✔
1754
        {
1755
            std::lock_guard<std::mutex> l(mtx_);
1,214✔
1756
            if (exception_)
1,214✔
1757
            {
1758
                std::exception_ptr e = exception_;
6✔
1759
                exception_ = std::exception_ptr();
6✔
1760
                std::rethrow_exception(e);
7✔
1761
            }
6✔
1762
        }
1,213✔
1763
    }
1,213✔
1764

1765
    ///////////////////////////////////////////////////////////////////////////
1766
    int runtime::run(hpx::function<hpx_main_function_type> const& func)
607✔
1767
    {
1768
        // start the main thread function
1769
        start(func);
607✔
1770

1771
        // now wait for everything to finish
1772
        wait();
607✔
1773
        stop();
607✔
1774

1775
        rethrow_exception();
607✔
1776
        return result_;
607✔
1777
    }
1778

1779
    ///////////////////////////////////////////////////////////////////////////
1780
    int runtime::run()
×
1781
    {
1782
        // start the main thread function
1783
        start();
×
1784

1785
        // now wait for everything to finish
1786
        int result = wait();
×
1787
        stop();
×
1788

1789
        rethrow_exception();
×
1790
        return result;
×
1791
    }
1792

1793
    util::thread_mapper& runtime::get_thread_mapper()
×
1794
    {
1795
        return *thread_support_;
×
1796
    }
1797

1798
    ///////////////////////////////////////////////////////////////////////////
1799
    threads::policies::callback_notifier runtime::get_notification_policy(
1,872✔
1800
        char const* prefix, runtime_local::os_thread_type type)
1801
    {
1802
        typedef bool (runtime::*report_error_t)(
1803
            std::size_t, std::exception_ptr const&, bool);
1804

1805
        using placeholders::_1;
1806
        using placeholders::_2;
1807
        using placeholders::_3;
1808
        using placeholders::_4;
1809

1810
        notification_policy_type notifier;
1,872✔
1811

1812
        notifier.add_on_start_thread_callback(
1,872✔
1813
            hpx::bind(&runtime::init_tss_helper, this, prefix, type, _1, _2, _3,
3,744✔
1814
                _4, false));
1,872✔
1815
        notifier.add_on_stop_thread_callback(
1,872✔
1816
            hpx::bind(&runtime::deinit_tss_helper, this, prefix, _1));
1,872✔
1817
        notifier.set_on_error_callback(
1,872✔
1818
            hpx::bind(static_cast<report_error_t>(&runtime::report_error), this,
3,744✔
1819
                _1, _2, true));
1,872✔
1820

1821
        return notifier;
1,872✔
1822
    }
1,872✔
1823

1824
    void runtime::init_tss_helper(char const* context,
5,779✔
1825
        runtime_local::os_thread_type type, std::size_t local_thread_num,
1826
        std::size_t global_thread_num, char const* pool_name,
1827
        char const* postfix, bool service_thread)
1828
    {
1829
        error_code ec(throwmode::lightweight);
5,820✔
1830
        return init_tss_ex(context, type, local_thread_num, global_thread_num,
11,558✔
1831
            pool_name, postfix, service_thread, ec);
5,820✔
1832
    }
5,820✔
1833

1834
    void runtime::init_tss_ex(char const* context,
5,797✔
1835
        runtime_local::os_thread_type type, std::size_t local_thread_num,
1836
        std::size_t global_thread_num, char const* pool_name,
1837
        char const* postfix, bool service_thread, error_code& ec)
1838
    {
1839
        // set the thread's name, if it's not already set
1840
        HPX_ASSERT(detail::thread_name().empty());
5,797✔
1841

1842
        std::string fullname;
5,820✔
1843
        fullname += context;
5,820✔
1844
        if (postfix && *postfix)
5,820✔
1845
            fullname += postfix;
×
1846
        fullname += "#" + std::to_string(global_thread_num);
5,820✔
1847
        detail::thread_name() = HPX_MOVE(fullname);
5,806✔
1848

1849
        char const* name = detail::thread_name().c_str();
5,795✔
1850

1851
        // initialize thread mapping for external libraries (i.e. PAPI)
1852
        thread_support_->register_thread(name, type);
5,821✔
1853

1854
        // register this thread with any possibly active Intel tool
1855
        HPX_ITT_THREAD_SET_NAME(name);
5,821✔
1856

1857
        // set thread name as shown in Visual Studio
1858
        util::set_thread_name(name);
5,821✔
1859

1860
#if defined(HPX_HAVE_APEX)
1861
        if (std::strstr(name, "worker") != nullptr)
1862
            util::external_timer::register_thread(name);
1863
#endif
1864

1865
        // call thread-specific user-supplied on_start handler
1866
        if (on_start_func_)
5,821✔
1867
        {
1868
            on_start_func_(
×
1869
                local_thread_num, global_thread_num, pool_name, context);
×
1870
        }
×
1871

1872
        // if this is a service thread, set its service affinity
1873
        if (service_thread)
5,821✔
1874
        {
1875
            // FIXME: We don't set the affinity of the service threads on BG/Q,
1876
            // as this is causing a hang (needs to be investigated)
1877
#if !defined(__bgq__)
1878
            threads::mask_cref_type used_processing_units =
1✔
1879
                thread_manager_->get_used_processing_units();
1✔
1880

1881
            // --hpx:bind=none  should disable all affinity definitions
1882
            if (threads::any(used_processing_units))
1✔
1883
            {
1884
                this->topology_.set_thread_affinity_mask(
1✔
1885
                    this->topology_.get_service_affinity_mask(
2✔
1886
                        used_processing_units),
1✔
1887
                    ec);
1✔
1888

1889
                // comment this out for now as on CircleCI this is causing
1890
                // unending grief
1891
                //if (ec)
1892
                //{
1893
                //    HPX_THROW_EXCEPTION(hpx::error::kernel_error,
1894
                //        "runtime::init_tss_ex",
1895
                //        "failed to set thread affinity mask ({}) for service "
1896
                //        "thread: {}",
1897
                //        hpx::threads::to_string(used_processing_units),
1898
                //        detail::thread_name());
1899
                //}
1900
            }
1✔
1901
#endif
1902
        }
1✔
1903
    }
5,821✔
1904

1905
    void runtime::deinit_tss_helper(
5,753✔
1906
        char const* context, std::size_t global_thread_num)
1907
    {
1908
        threads::reset_continuation_recursion_count();
5,710✔
1909

1910
        // call thread-specific user-supplied on_stop handler
1911
        if (on_stop_func_)
5,710✔
1912
        {
1913
            on_stop_func_(global_thread_num, global_thread_num, "", context);
×
1914
        }
×
1915

1916
        // reset PAPI support
1917
        thread_support_->unregister_thread();
5,710✔
1918

1919
        // reset thread local storage
1920
        detail::thread_name().clear();
5,710✔
1921
    }
5,710✔
1922

1923
    void runtime::add_pre_startup_function(startup_function_type f)
×
1924
    {
1925
        if (!f.empty())
×
1926
        {
1927
            std::lock_guard<std::mutex> l(mtx_);
×
1928
            pre_startup_functions_.push_back(HPX_MOVE(f));
×
1929
        }
×
1930
    }
×
1931

1932
    void runtime::add_startup_function(startup_function_type f)
4✔
1933
    {
1934
        if (!f.empty())
4✔
1935
        {
1936
            std::lock_guard<std::mutex> l(mtx_);
4✔
1937
            startup_functions_.push_back(HPX_MOVE(f));
4✔
1938
        }
4✔
1939
    }
4✔
1940

1941
    void runtime::add_pre_shutdown_function(shutdown_function_type f)
×
1942
    {
1943
        if (!f.empty())
×
1944
        {
1945
            std::lock_guard<std::mutex> l(mtx_);
×
1946
            pre_shutdown_functions_.push_back(HPX_MOVE(f));
×
1947
        }
×
1948
    }
×
1949

1950
    void runtime::add_shutdown_function(shutdown_function_type f)
1✔
1951
    {
1952
        if (!f.empty())
1✔
1953
        {
1954
            std::lock_guard<std::mutex> l(mtx_);
1✔
1955
            shutdown_functions_.push_back(HPX_MOVE(f));
1✔
1956
        }
1✔
1957
    }
1✔
1958

1959
    hpx::util::io_service_pool* runtime::get_thread_pool(char const* name)
2,916✔
1960
    {
1961
        HPX_ASSERT(name != nullptr);
2,916✔
1962
#ifdef HPX_HAVE_IO_POOL
1963
        if (0 == std::strncmp(name, "io", 2))
2,916✔
1964
            return &io_pool_;
1✔
1965
#endif
1966
#ifdef HPX_HAVE_TIMER_POOL
1967
        if (0 == std::strncmp(name, "timer", 5))
2,915✔
1968
            return &timer_pool_;
2,913✔
1969
#endif
1970
        if (0 == std::strncmp(name, "main", 4))    //-V112
2✔
1971
            return &main_pool_;
2✔
1972

1973
        HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
1974
            "runtime::get_thread_pool", "unknown thread pool requested: {}",
1975
            name);
1976
        return nullptr;
1977
    }
2,916✔
1978

1979
    /// Register an external OS-thread with HPX
1980
    bool runtime::register_thread(char const* name,
1✔
1981
        std::size_t global_thread_num, bool service_thread, error_code& ec)
1982
    {
1983
        std::string thread_name(name);
1✔
1984
        thread_name += "-thread";
1✔
1985

1986
        init_tss_ex(thread_name.c_str(),
2✔
1987
            runtime_local::os_thread_type::custom_thread, global_thread_num,
1✔
1988
            global_thread_num, "", nullptr, service_thread, ec);
1✔
1989

1990
        return !ec ? true : false;
1✔
1991
    }
1✔
1992

1993
    /// Unregister an external OS-thread with HPX
1994
    bool runtime::unregister_thread()
4✔
1995
    {
1996
        deinit_tss_helper(
4✔
1997
            detail::thread_name().c_str(), hpx::get_worker_thread_num());
4✔
1998
        return true;
4✔
1999
    }
2000

2001
    // Access data for a given OS thread that was previously registered by
2002
    // \a register_thread. This function must be called from a thread that was
2003
    // previously registered with the runtime.
2004
    runtime_local::os_thread_data runtime::get_os_thread_data(
×
2005
        std::string const& label) const
2006
    {
2007
        return thread_support_->get_os_thread_data(label);
×
2008
    }
2009

2010
    /// Enumerate all OS threads that have registered with the runtime.
2011
    bool runtime::enumerate_os_threads(
4✔
2012
        hpx::function<bool(os_thread_data const&)> const& f) const
2013
    {
2014
        return thread_support_->enumerate_os_threads(f);
4✔
2015
    }
2016

2017
    ///////////////////////////////////////////////////////////////////////////
2018
    threads::policies::callback_notifier get_notification_policy(
×
2019
        char const* prefix)
2020
    {
2021
        return get_runtime().get_notification_policy(
×
2022
            prefix, runtime_local::os_thread_type::worker_thread);
×
2023
    }
2024

2025
    std::uint32_t get_locality_id(error_code& ec)
57,273,229✔
2026
    {
2027
        runtime* rt = get_runtime_ptr();
57,260,692✔
2028
        if (nullptr == rt || rt->get_state() == state::invalid)
57,273,229✔
2029
        {
2030
            // same as naming::invalid_locality_id
2031
            return ~static_cast<std::uint32_t>(0);
647,206✔
2032
        }
2033

2034
        return rt->get_locality_id(ec);
56,536,360✔
2035
    }
57,184,208✔
2036

2037
    std::size_t get_num_worker_threads()
1,140✔
2038
    {
2039
        runtime* rt = get_runtime_ptr();
1,140✔
2040
        if (nullptr == rt)
1,140✔
2041
        {
2042
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2043
                "hpx::get_num_worker_threads",
2044
                "the runtime system has not been initialized yet");
2045
            return std::size_t(0);
2046
        }
2047

2048
        return rt->get_num_worker_threads();
1,140✔
2049
    }
×
2050

2051
    /// \brief Return the number of localities which are currently registered
2052
    ///        for the running application.
2053
    std::uint32_t get_num_localities(hpx::launch::sync_policy, error_code& ec)
311✔
2054
    {
2055
        runtime* rt = get_runtime_ptr();
311✔
2056
        if (nullptr == rt)
311✔
2057
        {
2058
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2059
                "hpx::get_num_localities",
2060
                "the runtime system has not been initialized yet");
2061
            return std::size_t(0);
2062
        }
2063

2064
        return rt->get_num_localities(hpx::launch::sync, ec);
311✔
2065
    }
×
2066

2067
    std::uint32_t get_initial_num_localities()
67,863✔
2068
    {
2069
        runtime* rt = get_runtime_ptr();
67,863✔
2070
        if (nullptr == rt)
67,863✔
2071
        {
2072
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2073
                "hpx::get_initial_num_localities",
2074
                "the runtime system has not been initialized yet");
2075
            return std::size_t(0);
2076
        }
2077

2078
        return rt->get_initial_num_localities();
67,863✔
2079
    }
×
2080

2081
    hpx::future<std::uint32_t> get_num_localities()
9✔
2082
    {
2083
        runtime* rt = get_runtime_ptr();
9✔
2084
        if (nullptr == rt)
9✔
2085
        {
2086
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
2087
                "hpx::get_num_localities",
2088
                "the runtime system has not been initialized yet");
2089
            return make_ready_future(std::uint32_t(0));
2090
        }
2091

2092
        return rt->get_num_localities();
9✔
2093
    }
×
2094

2095
    namespace threads {
2096
        char const* get_stack_size_name(std::ptrdiff_t size)
2✔
2097
        {
2098
            thread_stacksize size_enum = thread_stacksize::unknown;
2✔
2099

2100
            hpx::util::runtime_configuration const& rtcfg = hpx::get_config();
2✔
2101
            if (rtcfg.get_stack_size(thread_stacksize::small_) == size)
2✔
2102
                size_enum = thread_stacksize::small_;
×
2103
            else if (rtcfg.get_stack_size(thread_stacksize::medium) == size)
2✔
2104
                size_enum = thread_stacksize::medium;
×
2105
            else if (rtcfg.get_stack_size(thread_stacksize::large) == size)
2✔
2106
                size_enum = thread_stacksize::large;
2✔
2107
            else if (rtcfg.get_stack_size(thread_stacksize::huge) == size)
×
2108
                size_enum = thread_stacksize::huge;
×
2109
            else if (rtcfg.get_stack_size(thread_stacksize::nostack) == size)
×
2110
                size_enum = thread_stacksize::nostack;
×
2111

2112
            return get_stack_size_enum_name(size_enum);
2✔
2113
        }
2114
    }    // namespace threads
2115
}    // namespace hpx
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