• 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

48.91
/libs/full/init_runtime/src/hpx_init.cpp
1
//  Copyright (c) 2007-2022 Hartmut Kaiser
2
//  Copyright (c)      2017 Shoshana Jakobovits
3
//  Copyright (c) 2010-2011 Phillip LeBlanc, Dylan Stark
4
//  Copyright (c)      2011 Bryce Lelbach
5
//
6
//  SPDX-License-Identifier: BSL-1.0
7
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
8
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9

10
#include <hpx/hpx_init.hpp>
11

12
#include <hpx/assert.hpp>
13
#include <hpx/command_line_handling/command_line_handling.hpp>
14
#include <hpx/coroutines/detail/context_impl.hpp>
15
#include <hpx/execution/detail/execution_parameter_callbacks.hpp>
16
#include <hpx/executors/exception_list.hpp>
17
#include <hpx/functional/bind_front.hpp>
18
#include <hpx/functional/function.hpp>
19
#include <hpx/futures/detail/future_data.hpp>
20
#include <hpx/hpx_finalize.hpp>
21
#include <hpx/hpx_suspend.hpp>
22
#include <hpx/hpx_user_main_config.hpp>
23
#include <hpx/init_runtime/detail/init_logging.hpp>
24
#include <hpx/init_runtime/detail/run_or_start.hpp>
25
#include <hpx/init_runtime_local/init_runtime_local.hpp>
26
#include <hpx/lock_registration/detail/register_locks.hpp>
27
#include <hpx/modules/errors.hpp>
28
#include <hpx/modules/filesystem.hpp>
29
#include <hpx/modules/format.hpp>
30
#include <hpx/modules/logging.hpp>
31
#include <hpx/modules/schedulers.hpp>
32
#include <hpx/modules/testing.hpp>
33
#include <hpx/modules/timing.hpp>
34
#include <hpx/parallel/util/detail/handle_exception_termination_handler.hpp>
35
#include <hpx/program_options/parsers.hpp>
36
#include <hpx/program_options/variables_map.hpp>
37
#include <hpx/resource_partitioner/partitioner.hpp>
38
#include <hpx/runtime_local/config_entry.hpp>
39
#include <hpx/runtime_local/custom_exception_info.hpp>
40
#include <hpx/runtime_local/debugging.hpp>
41
#include <hpx/runtime_local/detail/serialize_exception.hpp>
42
#include <hpx/runtime_local/get_locality_id.hpp>
43
#include <hpx/runtime_local/report_error.hpp>
44
#include <hpx/runtime_local/runtime_handlers.hpp>
45
#include <hpx/runtime_local/runtime_local.hpp>
46
#include <hpx/runtime_local/runtime_local_fwd.hpp>
47
#include <hpx/runtime_local/shutdown_function.hpp>
48
#include <hpx/runtime_local/startup_function.hpp>
49
#include <hpx/string_util/classification.hpp>
50
#include <hpx/string_util/split.hpp>
51
#include <hpx/threading/thread.hpp>
52
#include <hpx/threading_base/detail/get_default_timer_service.hpp>
53
#include <hpx/type_support/pack.hpp>
54
#include <hpx/type_support/unused.hpp>
55
#include <hpx/util/from_string.hpp>
56

57
#ifdef HPX_HAVE_MODULE_MPI_BASE
58
#include <hpx/modules/mpi_base.hpp>
59
#endif
60
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
61
#include <hpx/actions_base/plain_action.hpp>
62
#include <hpx/async_distributed/bind_action.hpp>
63
#include <hpx/components_base/agas_interface.hpp>
64
#include <hpx/init_runtime/pre_main.hpp>
65
#include <hpx/modules/async_distributed.hpp>
66
#include <hpx/modules/naming.hpp>
67
#if defined(HPX_HAVE_NETWORKING)
68
#include <hpx/parcelset/parcelhandler.hpp>
69
#include <hpx/parcelset_base/locality_interface.hpp>
70
#endif
71
#include <hpx/performance_counters/counters.hpp>
72
#include <hpx/performance_counters/query_counters.hpp>
73
#include <hpx/runtime_distributed.hpp>
74
#include <hpx/runtime_distributed/find_localities.hpp>
75
#include <hpx/runtime_distributed/runtime_fwd.hpp>
76
#include <hpx/runtime_distributed/runtime_support.hpp>
77
#endif
78

79
#if defined(HPX_NATIVE_MIC) || defined(__bgq__)
80
#include <cstdlib>
81
#endif
82

83
#include <cmath>
84
#include <cstddef>
85
#include <exception>
86
#include <functional>
87
#include <iostream>
88
#include <map>
89
#include <memory>
90
#include <new>
91
#include <sstream>
92
#include <string>
93
#include <utility>
94
#include <vector>
95

96
#if !defined(HPX_WINDOWS)
97
#include <signal.h>
98
#endif
99

100
///////////////////////////////////////////////////////////////////////////////
101
namespace hpx_startup {
102
    std::vector<std::string> (*user_main_config_function)(
103
        std::vector<std::string> const&) = nullptr;
104
}
105

106
///////////////////////////////////////////////////////////////////////////////
107
namespace hpx { namespace detail {
108
    // forward declarations only
109
    void console_print(std::string const&);
110
}}    // namespace hpx::detail
111

112
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
113
namespace hpx { namespace detail {
114
    // forward declarations only
115
    void list_symbolic_name(std::string const&, hpx::id_type const&);
116
    void list_component_type(std::string const&, components::component_type);
117
}}    // namespace hpx::detail
118

119
HPX_PLAIN_ACTION_ID(hpx::detail::console_print, console_print_action,
4,636✔
120
    hpx::actions::console_print_action_id)
121
HPX_PLAIN_ACTION_ID(hpx::detail::list_component_type,
4,636✔
122
    list_component_type_action, hpx::actions::list_component_type_action_id)
123

124
typedef hpx::detail::bound_action<list_component_type_action,
125
    hpx::util::index_pack<0, 1, 2>, hpx::id_type, hpx::detail::placeholder<1>,
126
    hpx::detail::placeholder<2>>
127
    bound_list_component_type_action;
128

129
HPX_UTIL_REGISTER_FUNCTION_DECLARATION(
130
    void(std::string const&, hpx::components::component_type),
131
    bound_list_component_type_action, list_component_type_function)
132

133
HPX_UTIL_REGISTER_FUNCTION(
1,159✔
134
    void(std::string const&, hpx::components::component_type),
135
    bound_list_component_type_action, list_component_type_function)
136
#endif
137

138
namespace hpx { namespace detail {
139
    ///////////////////////////////////////////////////////////////////////////
140
    // print string on the console
141
    void console_print(std::string const& name)
×
142
    {
143
        std::cout << name << std::endl;
×
144
    }
×
145

146
    inline void print(std::string const& name, error_code& ec = throws)
×
147
    {
148
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
149
        hpx::id_type console(agas::get_console_locality(ec));
×
150
        if (ec)
×
151
            return;
×
152

153
        hpx::async<console_print_action>(console, name).get(ec);
×
154
        if (ec)
×
155
            return;
×
156
#else
157
        console_print(name);
158
#endif
159
        if (&ec != &throws)
×
160
            ec = make_success_code();
×
161
    }
×
162

163
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
164
    ///////////////////////////////////////////////////////////////////////////
165
    // redirect the printing of the given counter name to the console
166
    bool list_counter(
×
167
        performance_counters::counter_info const& info, error_code& ec)
168
    {
169
        print(info.fullname_, ec);
×
170
        return true;
×
171
    }
172

173
    // List the names of all registered performance counters.
174
    void list_counter_names_header(bool skeleton)
×
175
    {
176
        // print header
177
        print("List of available counter instances");
×
178
        if (skeleton)
×
179
            print("(replace '*' below with the appropriate sequence number)");
×
180
        print(std::string(78, '-'));
×
181
    }
×
182

183
    void list_counter_names_minimal()
×
184
    {
185
        // list all counter names
186
        list_counter_names_header(true);
×
187
        performance_counters::discover_counter_types(&list_counter,
×
188
            performance_counters::discover_counters_mode::minimal);
189
    }
×
190

191
    void list_counter_names_full()
×
192
    {
193
        // list all counter names
194
        list_counter_names_header(false);
×
195
        performance_counters::discover_counter_types(
×
196
            &list_counter, performance_counters::discover_counters_mode::full);
×
197
    }
×
198

199
    ///////////////////////////////////////////////////////////////////////////
200
    // redirect the printing of the full counter info to the console
201
    bool list_counter_info(
×
202
        performance_counters::counter_info const& info, error_code& ec)
203
    {
204
        // compose the information to be printed for each of the counters
205
        std::ostringstream strm;
×
206

207
        strm << std::string(78, '-') << '\n';
×
208
        strm << "fullname: " << info.fullname_ << '\n';
×
209
        strm << "helptext: " << info.helptext_ << '\n';
×
210
        strm << "type:     "
×
211
             << performance_counters::get_counter_type_name(info.type_) << '\n';
×
212

213
        strm << "version:  ";    // 0xMMmmrrrr
×
214
        hpx::util::format_to(strm, "{}.{}.{}\n", info.version_ / 0x1000000,
×
215
            info.version_ / 0x10000 % 0x100, info.version_ % 0x10000);
×
216
        strm << std::string(78, '-') << '\n';
×
217

218
        print(strm.str(), ec);
×
219

220
        if (&ec != &throws)
×
221
            ec = make_success_code();
×
222
        return true;
223
    }
×
224

225
    // List the names of all registered performance counters.
226
    void list_counter_infos_header(bool skeleton)
×
227
    {
228
        // print header
229
        print("Information about available counter instances");
×
230
        if (skeleton)
×
231
            print("(replace '*' below with the appropriate sequence number)");
×
232
        print("--------------------------------------------------------");
×
233
    }
×
234

235
    void list_counter_infos_minimal()
×
236
    {
237
        // list all counter information
238
        list_counter_infos_header(true);
×
239
        performance_counters::discover_counter_types(&list_counter_info,
×
240
            performance_counters::discover_counters_mode::minimal);
241
    }
×
242

243
    void list_counter_infos_full()
×
244
    {
245
        // list all counter information
246
        list_counter_infos_header(false);
×
247
        performance_counters::discover_counter_types(&list_counter_info,
×
248
            performance_counters::discover_counters_mode::full);
249
    }
×
250

251
    ///////////////////////////////////////////////////////////////////////////
252
    void list_symbolic_name(std::string const& name, hpx::id_type const& id)
×
253
    {
254
        std::string str = hpx::util::format("{}, {}, {}", name, id,
×
255
            (id.get_management_type() == id_type::management_type::managed ?
×
256
                    "management_type::managed" :
257
                    "management_type::unmanaged"));
258
        print(str);
×
259
    }
×
260

261
    void list_symbolic_names()
×
262
    {
263
        print(std::string("List of all registered symbolic names:"));
×
264
        print(std::string("--------------------------------------"));
×
265

266
        std::map<std::string, hpx::id_type> entries =
267
            agas::find_symbols(hpx::launch::sync);
×
268

269
        for (auto const& e : entries)
×
270
        {
271
            list_symbolic_name(e.first, e.second);
×
272
        }
273
    }
×
274

275
    ///////////////////////////////////////////////////////////////////////////
276
    void list_component_type(
×
277
        std::string const& name, components::component_type ctype)
278
    {
279
        print(hpx::util::format(
×
280
            "{1:-40}, {2}", name, components::get_component_type_name(ctype)));
×
281
    }
×
282

283
    void list_component_types()
×
284
    {
285
        print(std::string("List of all registered component types:"));
×
286
        print(std::string("---------------------------------------"));
×
287

288
        using hpx::placeholders::_1;
289
        using hpx::placeholders::_2;
290

291
        hpx::id_type console(agas::get_console_locality());
×
292
        naming::get_agas_client().iterate_types(
×
293
            hpx::bind<list_component_type_action>(console, _1, _2));
×
294
    }
×
295

296
    ///////////////////////////////////////////////////////////////////////////
297
    void start_counters(std::shared_ptr<util::query_counters> const& qc)
×
298
    {
299
        try
300
        {
301
            HPX_ASSERT(qc);
×
302
            qc->start();
×
303
        }
×
304
        catch (...)
305
        {
306
            std::cerr << hpx::diagnostic_information(std::current_exception())
×
307
                      << std::flush;
×
308
            hpx::terminate();
×
309
        }
×
310
    }
×
311
#endif
312
}}    // namespace hpx::detail
313

314
///////////////////////////////////////////////////////////////////////////////
315
#if defined(HPX_HAVE_DYNAMIC_HPX_MAIN) &&                                      \
316
    (defined(__linux) || defined(__linux__) || defined(linux) ||               \
317
        defined(__APPLE__))
318
namespace hpx_start {
319
    // Importing weak symbol from libhpx_wrap.a which may be shadowed by one present in
320
    // hpx_main.hpp.
321
    HPX_SYMBOL_EXPORT __attribute__((weak)) bool include_libhpx_wrap = false;
322
}    // namespace hpx_start
323

324
#endif
325

326
///////////////////////////////////////////////////////////////////////////////
327
namespace hpx {
328
    // Print stack trace and exit.
329
#if defined(HPX_WINDOWS)
330
    extern BOOL WINAPI termination_handler(DWORD ctrl_type);
331
#else
332
    extern void termination_handler(int signum);
333
#endif
334

335
    ///////////////////////////////////////////////////////////////////////////
336
    namespace detail {
337

338
        ///////////////////////////////////////////////////////////////////////
339
        void activate_global_options(
597✔
340
            util::command_line_handling& cmdline, int argc, char** argv)
341
        {
342
#if defined(__linux) || defined(linux) || defined(__linux__) ||                \
343
    defined(__FreeBSD__)
344
            threads::coroutines::detail::posix::use_guard_pages =
597✔
345
                cmdline.rtcfg_.use_stack_guard_pages();
597✔
346
#endif
347
#ifdef HPX_HAVE_VERIFY_LOCKS
348
            if (cmdline.rtcfg_.enable_lock_detection())
597✔
349
            {
350
                util::enable_lock_detection();
597✔
351
                util::trace_depth_lock_detection(cmdline.rtcfg_.trace_depth());
597✔
352
            }
597✔
353
            else
354
            {
355
                util::disable_lock_detection();
×
356
            }
357
#endif
358
#ifdef HPX_HAVE_THREAD_MINIMAL_DEADLOCK_DETECTION
359
            threads::policies::set_minimal_deadlock_detection_enabled(
360
                cmdline.rtcfg_.enable_minimal_deadlock_detection());
361
#endif
362
#ifdef HPX_HAVE_SPINLOCK_DEADLOCK_DETECTION
363
            util::detail::set_spinlock_break_on_deadlock_enabled(
597✔
364
                cmdline.rtcfg_.enable_spinlock_deadlock_detection());
597✔
365
            util::detail::set_spinlock_deadlock_detection_limit(
597✔
366
                cmdline.rtcfg_.get_spinlock_deadlock_detection_limit());
597✔
367
#endif
368

369
#if defined(HPX_HAVE_LOGGING)
370
            util::detail::init_logging_full(cmdline.rtcfg_);
597✔
371
#else
372
            util::detail::warn_if_logging_requested(cmdline.rtcfg_);
373
#endif
374

375
#if defined(HPX_HAVE_NETWORKING)
376
            if (cmdline.num_localities_ != 1 || cmdline.node_ != 0 ||
597✔
377
                cmdline.rtcfg_.enable_networking())
317✔
378
            {
379
                parcelset::parcelhandler::init(&argc, &argv, cmdline);
283✔
380
            }
283✔
381
#endif
382
            HPX_UNUSED(argc);
597✔
383
            HPX_UNUSED(argv);
597✔
384
        }
597✔
385

386
        ///////////////////////////////////////////////////////////////////////
387
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
388
        void handle_list_and_print_options(hpx::runtime& rt,
451✔
389
            hpx::program_options::variables_map& vm,
390
            bool print_counters_locally)
391
        {
392
            runtime_distributed* rtd =
451✔
393
                dynamic_cast<hpx::runtime_distributed*>(&rt);
451✔
394
            HPX_ASSERT(rtd != nullptr);
451✔
395
            if (vm.count("hpx:list-counters"))
451✔
396
            {
397
                // Print the names of all registered performance counters.
398
                std::string option(vm["hpx:list-counters"].as<std::string>());
×
399
                if (0 == std::string("minimal").find(option))
×
400
                    rt.add_startup_function(&list_counter_names_minimal);
×
401
                else if (0 == std::string("full").find(option))
×
402
                    rt.add_startup_function(&list_counter_names_full);
×
403
                else
404
                {
405
                    std::string msg("Invalid command line option value"
×
406
                                    "for --hpx:list-counters: ");
407
                    msg += option;
×
408
                    msg += ", allowed values are 'minimal' and 'full'";
×
409
                    throw detail::command_line_error(msg.c_str());
×
410
                }
×
411
            }
×
412
            if (vm.count("hpx:list-counter-infos"))
451✔
413
            {
414
                // Print info about all registered performance counters.
415
                std::string option(
×
416
                    vm["hpx:list-counter-infos"].as<std::string>());
×
417
                if (0 == std::string("minimal").find(option))
×
418
                    rt.add_startup_function(&list_counter_infos_minimal);
×
419
                else if (0 == std::string("full").find(option))
×
420
                    rt.add_startup_function(&list_counter_infos_full);
×
421
                else
422
                {
423
                    std::string msg("Invalid command line option value"
×
424
                                    "for --hpx:list-counter-infos: ");
425
                    msg += option;
×
426
                    msg += ", allowed values are 'minimal' and 'full'";
×
427
                    throw detail::command_line_error(msg.c_str());
×
428
                }
×
429
            }
×
430
            if (vm.count("hpx:list-symbolic-names"))
451✔
431
            {
432
                // Print all registered symbolic names.
433
                rt.add_startup_function(&list_symbolic_names);
×
434
            }
×
435
            if (vm.count("hpx:list-component-types"))
451✔
436
            {
437
                // Print all registered component types.
438
                rt.add_startup_function(&list_component_types);
×
439
            }
×
440

441
            if (vm.count("hpx:print-counter") ||
902✔
442
                vm.count("hpx:print-counter-reset"))
451✔
443
            {
444
                std::size_t interval = 0;
×
445
                if (vm.count("hpx:print-counter-interval"))
×
446
                {
447
                    interval =
×
448
                        vm["hpx:print-counter-interval"].as<std::size_t>();
×
449
                }
×
450

451
                std::vector<std::string> counters;
×
452
                if (vm.count("hpx:print-counter"))
×
453
                {
454
                    counters =
×
455
                        vm["hpx:print-counter"].as<std::vector<std::string>>();
×
456
                }
×
457

458
                std::vector<std::string> reset_counters;
×
459
                if (vm.count("hpx:print-counter-reset"))
×
460
                {
461
                    reset_counters = vm["hpx:print-counter-reset"]
×
462
                                         .as<std::vector<std::string>>();
×
463
                }
×
464

465
                std::vector<std::string> counter_shortnames;
×
466
                std::string counter_format("normal");
×
467
                if (vm.count("hpx:print-counter-format"))
×
468
                {
469
                    counter_format =
×
470
                        vm["hpx:print-counter-format"].as<std::string>();
×
471
                    if (counter_format == "csv-short")
×
472
                    {
473
                        for (std::size_t i = 0; i != counters.size(); ++i)
×
474
                        {
475
                            std::vector<std::string> entry;
×
476
                            hpx::string_util::split(entry, counters[i],
×
477
                                hpx::string_util::is_any_of(","),
×
478
                                hpx::string_util::token_compress_mode::on);
479

480
                            if (entry.size() != 2)
×
481
                            {
482
                                throw detail::command_line_error(
×
483
                                    "Invalid format for command line "
484
                                    "option "
485
                                    "--hpx:print-counter-format=csv-short");
486
                            }
487

488
                            counter_shortnames.push_back(entry[0]);
×
489
                            counters[i] = entry[1];
×
490
                        }
×
491
                    }
×
492
                }
×
493

494
                bool csv_header = true;
×
495
                if (vm.count("hpx:no-csv-header"))
×
496
                    csv_header = false;
×
497

498
                std::string destination("cout");
×
499
                if (vm.count("hpx:print-counter-destination"))
×
500
                    destination =
×
501
                        vm["hpx:print-counter-destination"].as<std::string>();
×
502

503
                bool counter_types = false;
×
504
                if (vm.count("hpx:print-counter-types"))
×
505
                    counter_types = true;
×
506

507
                // schedule the query function at startup, which will schedule
508
                // itself to run after the given interval
509
                std::shared_ptr<util::query_counters> qc =
510
                    std::make_shared<util::query_counters>(std::ref(counters),
×
511
                        std::ref(reset_counters), interval, destination,
×
512
                        counter_format, counter_shortnames, csv_header,
513
                        print_counters_locally, counter_types);
514

515
                // schedule to print counters at shutdown, if requested
516
                if (get_config_entry("hpx.print_counter.shutdown", "0") == "1")
×
517
                {
518
                    // schedule to run at shutdown
519
                    rt.add_pre_shutdown_function(hpx::bind_front(
×
520
                        &util::query_counters::evaluate, qc, true));
×
521
                }
×
522

523
                // schedule to start all counters
524

525
                rt.add_startup_function(hpx::bind_front(&start_counters, qc));
×
526

527
                // register the query_counters object with the runtime system
528
                rtd->register_query_counters(qc);
×
529
            }
×
530
            else if (vm.count("hpx:print-counter-interval"))
451✔
531
            {
532
                throw detail::command_line_error(
×
533
                    "Invalid command line option "
534
                    "--hpx:print-counter-interval, valid in conjunction "
535
                    "with "
536
                    "--hpx:print-counter only");
537
            }
538
            else if (vm.count("hpx:print-counter-destination"))
451✔
539
            {
540
                throw detail::command_line_error(
×
541
                    "Invalid command line option "
542
                    "--hpx:print-counter-destination, valid in conjunction "
543
                    "with "
544
                    "--hpx:print-counter only");
545
            }
546
            else if (vm.count("hpx:print-counter-format"))
451✔
547
            {
548
                throw detail::command_line_error(
×
549
                    "Invalid command line option "
550
                    "--hpx:print-counter-format, valid in conjunction with "
551
                    "--hpx:print-counter only");
552
            }
553
            else if (vm.count("hpx:print-counter-at"))
451✔
554
            {
555
                throw detail::command_line_error(
×
556
                    "Invalid command line option "
557
                    "--hpx:print-counter-at, valid in conjunction with "
558
                    "--hpx:print-counter only");
559
            }
560
            else if (vm.count("hpx:reset-counters"))
451✔
561
            {
562
                throw detail::command_line_error(
×
563
                    "Invalid command line option "
564
                    "--hpx:reset-counters, valid in conjunction with "
565
                    "--hpx:print-counter only");
566
            }
567
        }
451✔
568
#endif
569

570
        void add_startup_functions(hpx::runtime& rt,
597✔
571
            hpx::program_options::variables_map& vm, runtime_mode mode,
572
            startup_function_type startup, shutdown_function_type shutdown)
573
        {
574
            if (vm.count("hpx:app-config"))
597✔
575
            {
576
                std::string config(vm["hpx:app-config"].as<std::string>());
×
577
                rt.get_config().load_application_configuration(config.c_str());
×
578
            }
×
579

580
            if (!!startup)
597✔
581
                rt.add_startup_function(HPX_MOVE(startup));
×
582

583
            if (!!shutdown)
597✔
584
                rt.add_shutdown_function(HPX_MOVE(shutdown));
×
585

586
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
587
            // Add startup function related to listing counter names or counter
588
            // infos (on console only).
589
            bool print_counters_locally =
597✔
590
                vm.count("hpx:print-counters-locally") != 0;
597✔
591
            if (mode == runtime_mode::console || print_counters_locally)
597✔
592
                handle_list_and_print_options(rt, vm, print_counters_locally);
451✔
593
#else
594
            HPX_UNUSED(mode);
595
#endif
596

597
            // Dump the configuration before all components have been loaded.
598
            if (vm.count("hpx:dump-config-initial"))
597✔
599
            {
600
                std::cout << "Configuration after runtime construction:\n";
×
601
                std::cout << "-----------------------------------------\n";
×
602
                rt.get_config().dump(0, std::cout);
×
603
                std::cout << "-----------------------------------------\n";
×
604
            }
×
605

606
            // Dump the configuration after all components have been loaded.
607
            if (vm.count("hpx:dump-config"))
597✔
608
                rt.add_startup_function(hpx::local::detail::dump_config(rt));
×
609
        }
597✔
610

611
        ///////////////////////////////////////////////////////////////////////
612
        int run(hpx::runtime& rt,
491✔
613
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
614
                f,
615
            hpx::program_options::variables_map& vm, runtime_mode mode,
616
            startup_function_type startup, shutdown_function_type shutdown)
617
        {
618
            LPROGRESS_;
491✔
619

620
            add_startup_functions(
492✔
621
                rt, vm, mode, HPX_MOVE(startup), HPX_MOVE(shutdown));
491✔
622

623
            // Run this runtime instance using the given function f.
624
            if (!f.empty())
491✔
625
                return rt.run(hpx::bind_front(f, vm));
374✔
626

627
            // Run this runtime instance without an hpx_main
628
            return rt.run();
116✔
629
        }
489✔
630

631
        int start(hpx::runtime& rt,
106✔
632
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
633
                f,
634
            hpx::program_options::variables_map& vm, runtime_mode mode,
635
            startup_function_type startup, shutdown_function_type shutdown)
636
        {
637
            LPROGRESS_;
106✔
638

639
            add_startup_functions(
106✔
640
                rt, vm, mode, HPX_MOVE(startup), HPX_MOVE(shutdown));
106✔
641

642
            if (!f.empty())
106✔
643
            {
644
                // Run this runtime instance using the given function f.
645
                return rt.start(hpx::bind_front(f, vm));
105✔
646
            }
647

648
            // Run this runtime instance without an hpx_main
649
            return rt.start();
1✔
650
        }
106✔
651

652
        int run_or_start(bool blocking, std::unique_ptr<hpx::runtime> rt,
597✔
653
            util::command_line_handling& cfg, startup_function_type startup,
654
            shutdown_function_type shutdown)
655
        {
656
            if (blocking)
597✔
657
            {
658
                return run(*rt, cfg.hpx_main_f_, cfg.vm_, cfg.rtcfg_.mode_,
982✔
659
                    HPX_MOVE(startup), HPX_MOVE(shutdown));
489✔
660
            }
661

662
            // non-blocking version
663
            start(*rt, cfg.hpx_main_f_, cfg.vm_, cfg.rtcfg_.mode_,
212✔
664
                HPX_MOVE(startup), HPX_MOVE(shutdown));
106✔
665

666
            // pointer to runtime is stored in TLS
667
            hpx::runtime* p = rt.release();
106✔
668
            (void) p;
669

670
            return 0;
106✔
671
        }
595✔
672

673
        ////////////////////////////////////////////////////////////////////////
674
        void init_environment()
597✔
675
        {
676
            HPX_UNUSED(hpx::filesystem::initial_path());
597✔
677

678
            hpx::assertion::set_assertion_handler(&detail::assertion_handler);
597✔
679
            hpx::util::set_test_failure_handler(&detail::test_failure_handler);
597✔
680
#if defined(HPX_HAVE_APEX)
681
            hpx::util::set_enable_parent_task_handler(
682
                &detail::enable_parent_task_handler);
683
#endif
684
            hpx::set_custom_exception_info_handler(
597✔
685
                &detail::custom_exception_info);
597✔
686
            hpx::serialization::detail::set_save_custom_exception_handler(
597✔
687
                &runtime_local::detail::save_custom_exception);
597✔
688
            hpx::serialization::detail::set_load_custom_exception_handler(
597✔
689
                &runtime_local::detail::load_custom_exception);
597✔
690
            hpx::set_pre_exception_handler(&detail::pre_exception_handler);
597✔
691
            hpx::set_thread_termination_handler(
597✔
692
                [](std::exception_ptr const& e) { report_error(e); });
597✔
693
            hpx::lcos::detail::set_run_on_completed_error_handler(
597✔
694
                [](std::exception_ptr const& e) {
597✔
695
                    report_exception_and_terminate(e);
×
696
                });
697
#if defined(HPX_HAVE_VERIFY_LOCKS)
698
            hpx::util::set_registered_locks_error_handler(
597✔
699
                &detail::registered_locks_error_handler);
597✔
700
            hpx::util::set_register_locks_predicate(
597✔
701
                &detail::register_locks_predicate);
597✔
702
#endif
703
#if !defined(HPX_HAVE_DISABLED_SIGNAL_EXCEPTION_HANDLERS)
704
            set_error_handlers();
597✔
705
#endif
706
            hpx::threads::detail::set_get_default_pool(
597✔
707
                &detail::get_default_pool);
597✔
708
            hpx::threads::detail::set_get_default_timer_service(
597✔
709
                &hpx::detail::get_default_timer_service);
597✔
710
            hpx::threads::detail::set_get_locality_id(&get_locality_id);
597✔
711
            hpx::parallel::execution::detail::set_get_pu_mask(
597✔
712
                &hpx::detail::get_pu_mask);
597✔
713
            hpx::parallel::execution::detail::set_get_os_thread_count(
597✔
714
                []() { return hpx::get_os_thread_count(); });
868✔
715
            hpx::parallel::v1::detail::set_exception_list_termination_handler(
597✔
716
                &hpx::terminate);
597✔
717
            hpx::parallel::util::detail::
597✔
718
                set_parallel_exception_termination_handler(&hpx::terminate);
597✔
719

720
            // instantiate the interface function initialization objects
721
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
722
#if defined(HPX_HAVE_NETWORKING)
723
            parcelset::locality_init();
597✔
724
#endif
725
            agas::agas_init();
597✔
726
            agas::runtime_components_init();
597✔
727
            components::counter_init();
597✔
728
#endif
729

730
#if defined(HPX_NATIVE_MIC) || defined(__bgq__) || defined(__bgqion__)
731
            unsetenv("LANG");
732
            unsetenv("LC_CTYPE");
733
            unsetenv("LC_NUMERIC");
734
            unsetenv("LC_TIME");
735
            unsetenv("LC_COLLATE");
736
            unsetenv("LC_MONETARY");
737
            unsetenv("LC_MESSAGES");
738
            unsetenv("LC_PAPER");
739
            unsetenv("LC_NAME");
740
            unsetenv("LC_ADDRESS");
741
            unsetenv("LC_TELEPHONE");
742
            unsetenv("LC_MEASUREMENT");
743
            unsetenv("LC_IDENTIFICATION");
744
            unsetenv("LC_ALL");
745
#endif
746
        }
597✔
747

748
        // make sure the runtime system is not active yet
749
        int ensure_no_runtime_is_up()
597✔
750
        {
751
            // make sure the runtime system is not active yet
752
            if (get_runtime_ptr() != nullptr)
597✔
753
            {
754
#if defined(HPX_HAVE_DYNAMIC_HPX_MAIN) &&                                      \
755
    (defined(__linux) || defined(__linux__) || defined(linux) ||               \
756
        defined(__APPLE__))
757
                // make sure the runtime system is not initialized
758
                // after its activation from int main()
759
                if (hpx_start::include_libhpx_wrap)
×
760
                {
761
                    std::cerr
762
                        << "hpx is already initialized from main.\n"
×
763
                           "Note: Delete hpx_main.hpp to initialize hpx system "
764
                           "using hpx::init. Exiting...\n";
765
                    return -1;
×
766
                }
767
#endif
768
                std::cerr << "hpx::init: can't initialize runtime system "
×
769
                             "more than once! Exiting...\n";
770
                return -1;
×
771
            }
772
            return 0;
597✔
773
        }
597✔
774

775
        ///////////////////////////////////////////////////////////////////////
776
        int run_or_start(
597✔
777
            hpx::function<int(hpx::program_options::variables_map& vm)> const&
778
                f,
779
            int argc, char** argv, init_params const& params, bool blocking)
780
        {
781
            init_environment();
597✔
782

783
            int result = 0;
597✔
784
            try
785
            {
786
                // make sure the runtime system is not active yet
787
                if ((result = ensure_no_runtime_is_up()) != 0)
597✔
788
                {
789
                    return result;
×
790
                }
791

792
#if defined(HPX_HAVE_NETWORKING)
793
                hpx::util::command_line_handling cmdline{
597✔
794
                    hpx::util::runtime_configuration(argv[0], params.mode,
597✔
795
                        hpx::parcelset::load_runtime_configuration()),
597✔
796
                    hpx_startup::user_main_config(params.cfg), f};
597✔
797
#else
798
                hpx::util::command_line_handling cmdline{
799
                    hpx::util::runtime_configuration(argv[0], params.mode, {}),
800
                    hpx_startup::user_main_config(params.cfg), f};
801
#endif
802

803
                // scope exception handling to resource partitioner initialization
804
                // any exception thrown during run_or_start below are handled
805
                // separately
806
                try
807
                {
808
                    std::vector<
809
                        std::shared_ptr<components::component_registry_base>>
810
                        component_registries;
597✔
811

812
                    result = cmdline.call(
597✔
813
                        params.desc_cmdline, argc, argv, component_registries);
597✔
814

815
                    hpx::threads::policies::detail::affinity_data
816
                        affinity_data{};
597✔
817
                    affinity_data.init(hpx::util::get_entry_as<std::size_t>(
1,194✔
818
                                           cmdline.rtcfg_, "hpx.os_threads", 0),
597✔
819
                        hpx::util::get_entry_as<std::size_t>(
597✔
820
                            cmdline.rtcfg_, "hpx.cores", 0),
597✔
821
                        hpx::util::get_entry_as<std::size_t>(
597✔
822
                            cmdline.rtcfg_, "hpx.pu_offset", 0),
597✔
823
                        hpx::util::get_entry_as<std::size_t>(
597✔
824
                            cmdline.rtcfg_, "hpx.pu_step", 0),
597✔
825
                        static_cast<std::size_t>(
826
                            cmdline.rtcfg_.get_first_used_core()),
597✔
827
                        cmdline.rtcfg_.get_entry("hpx.affinity", ""),
597✔
828
                        cmdline.rtcfg_.get_entry("hpx.bind", ""),
597✔
829
                        hpx::util::get_entry_as<bool>(
597✔
830
                            cmdline.rtcfg_, "hpx.use_process_mask", 0));
597✔
831

832
                    hpx::resource::partitioner rp =
833
                        hpx::resource::detail::make_partitioner(
597✔
834
                            params.rp_mode, cmdline.rtcfg_, affinity_data);
597✔
835

836
                    for (auto& registry : component_registries)
1,182✔
837
                    {
838
                        hpx::register_startup_function([registry]() {
2,923✔
839
                            registry->register_component_type();
585✔
840
                        });
585✔
841
                    }
842

843
                    activate_global_options(cmdline, argc, argv);
597✔
844

845
                    // check whether HPX should be exited at this point
846
                    // (parse_result is returning a result > 0, if the program options
847
                    // contain --hpx:help or --hpx:version, on error result is < 0)
848
                    if (result != 0)
597✔
849
                    {
850
                        if (result > 0)
×
851
                            result = 0;
×
852
                        return result;
×
853
                    }
854

855
                    // If thread_pools initialization in user main
856
                    if (params.rp_callback)
597✔
857
                    {
858
                        params.rp_callback(rp, cmdline.vm_);
×
859
                    }
×
860

861
#if defined(HPX_HAVE_NETWORKING)
862
                    if (cmdline.num_localities_ != 1 || cmdline.node_ != 0 ||
914✔
863
                        cmdline.rtcfg_.enable_networking())
317✔
864
                    {
865
                        parcelset::parcelhandler::init(rp);
283✔
866
                    }
283✔
867
#endif
868
                    // Setup all internal parameters of the resource_partitioner
869
                    rp.configure_pools();
597✔
870
                }
597✔
871
                catch (hpx::exception const& e)
872
                {
873
                    std::cerr << "hpx::init: hpx::exception caught: "
×
874
                              << hpx::get_error_what(e) << "\n";
×
875
                    return -1;
×
876
                }
×
877

878
                // Initialize and start the HPX runtime.
879
                LPROGRESS_ << "run_local: create runtime";
597✔
880

881
                // Build and configure this runtime instance.
882
                std::unique_ptr<hpx::runtime> rt;
597✔
883

884
                // Command line handling should have updated this by now.
885
                HPX_ASSERT(cmdline.rtcfg_.mode_ != runtime_mode::default_);
597✔
886
                switch (cmdline.rtcfg_.mode_)
597✔
887
                {
888
                case runtime_mode::local:
889
                {
890
                    LPROGRESS_ << "creating local runtime";
4✔
891
                    rt.reset(new hpx::runtime(cmdline.rtcfg_, true));
4✔
892
                    break;
4✔
893
                }
894
                default:
895
                {
896
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
897
                    LPROGRESS_ << "creating distributed runtime";
593✔
898
                    rt.reset(new hpx::runtime_distributed(cmdline.rtcfg_,
593✔
899
                        &hpx::detail::pre_main, &hpx::detail::post_main));
900
                    break;
593✔
901
#else
902
                    HPX_THROW_EXCEPTION(hpx::error::invalid_status,
903
                        "run_or_start",
904
                        "Attempted to start the runtime in the mode \"{1}\", "
905
                        "but HPX was compiled with "
906
                        "HPX_WITH_DISTRIBUTED_RUNTIME=OFF, and \"{1}\" "
907
                        "requires HPX_WITH_DISTRIBUTED_RUNTIME=ON. "
908
                        "Recompile HPX with HPX_WITH_DISTRIBUTED_RUNTIME=ON or "
909
                        "change the runtime mode.",
910
                        get_runtime_mode_name(cmdline.rtcfg_.mode_));
911
                    break;
912
#endif
913
                }
914
                }
915

916
                result = run_or_start(blocking, HPX_MOVE(rt), cmdline,
1,194✔
917
                    HPX_MOVE(params.startup), HPX_MOVE(params.shutdown));
595✔
918
            }
595✔
919
            catch (detail::command_line_error const& e)
920
            {
921
                std::cerr << "hpx::init: std::exception caught: " << e.what()
×
922
                          << "\n";
×
923
                return -1;
×
924
            }
×
925
            return result;
594✔
926
        }
595✔
927

928
        ////////////////////////////////////////////////////////////////////////
929
        template <typename T>
930
        inline T get_option(std::string const& config, T default_ = T())
962✔
931
        {
932
            if (!config.empty())
962✔
933
            {
934
                try
935
                {
936
                    return hpx::util::from_string<T>(
962✔
937
                        get_runtime().get_config().get_entry(config, default_));
962✔
938
                }
×
939
                catch (hpx::util::bad_lexical_cast const&)
940
                {
941
                    ;    // do nothing
942
                }
×
943
            }
×
944
            return default_;
×
945
        }
962✔
946
    }    // namespace detail
947

948
    ///////////////////////////////////////////////////////////////////////////
949
    int finalize(double shutdown_timeout, double localwait, error_code& ec)
480✔
950
    {
951
        if (!threads::get_self_ptr())
480✔
952
        {
953
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
×
954
                "this function can be called from an HPX thread only");
955
            return -1;
×
956
        }
957

958
        if (!is_running())
480✔
959
        {
960
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
×
961
                "the runtime system is not active (did you already "
962
                "call finalize?)");
963
            return -1;
×
964
        }
965

966
        if (&ec != &throws)
480✔
967
            ec = make_success_code();
×
968

969
        if (std::abs(localwait + 1.0) < 1e-16)
480✔
970
            localwait = detail::get_option("hpx.finalize_wait_time", -1.0);
480✔
971

972
        {
973
            hpx::chrono::high_resolution_timer t;
480✔
974
            double start_time = t.elapsed();
480✔
975
            double current = 0.0;
480✔
976
            do
480✔
977
            {
978
                current = t.elapsed();
480✔
979
            } while (current - start_time < localwait * 1e-6);
480✔
980
        }
981

982
        if (std::abs(shutdown_timeout + 1.0) < 1e-16)
480✔
983
            shutdown_timeout = detail::get_option("hpx.shutdown_timeout", -1.0);
480✔
984

985
        runtime* rt = get_runtime_ptr();
480✔
986
        if (nullptr == rt)
480✔
987
        {
988
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::finalize",
×
989
                "the runtime system is not active (did you already "
990
                "call hpx::stop?)");
991
            return -1;
×
992
        }
993

994
        rt->finalize(shutdown_timeout);
480✔
995

996
        return 0;
480✔
997
    }
480✔
998

999
    ///////////////////////////////////////////////////////////////////////////
1000
    int disconnect(double shutdown_timeout, double localwait, error_code& ec)
1✔
1001
    {
1002
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
1003
        if (!threads::get_self_ptr())
1✔
1004
        {
1005
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
×
1006
                "this function can be called from an HPX thread only");
1007
            return -1;
×
1008
        }
1009

1010
        if (!is_running())
1✔
1011
        {
1012
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
×
1013
                "the runtime system is not active (did you already "
1014
                "call finalize?)");
1015
            return -1;
×
1016
        }
1017

1018
        if (&ec != &throws)
1✔
1019
            ec = make_success_code();
×
1020

1021
        if (std::abs(localwait + 1.0) < 1e-16)
1✔
1022
            localwait = detail::get_option("hpx.finalize_wait_time", -1.0);
1✔
1023

1024
        {
1025
            hpx::chrono::high_resolution_timer t;
1✔
1026
            double start_time = t.elapsed();
1✔
1027
            double current = 0.0;
1✔
1028
            do
1✔
1029
            {
1030
                current = t.elapsed();
1✔
1031
            } while (current - start_time < localwait * 1e-6);
1✔
1032
        }
1033

1034
        if (std::abs(shutdown_timeout + 1.0) < 1e-16)
1✔
1035
            shutdown_timeout = detail::get_option("hpx.shutdown_timeout", -1.0);
1✔
1036

1037
        components::server::runtime_support* p =
1✔
1038
            static_cast<components::server::runtime_support*>(
1✔
1039
                get_runtime_distributed().get_runtime_support_lva());
1✔
1040

1041
        if (nullptr == p)
1✔
1042
        {
1043
            HPX_THROWS_IF(ec, hpx::error::invalid_status, "hpx::disconnect",
×
1044
                "the runtime system is not active (did you already "
1045
                "call finalize?)");
1046
            return -1;
×
1047
        }
1048

1049
        p->call_shutdown_functions(true);
1✔
1050
        p->call_shutdown_functions(false);
1✔
1051

1052
        p->stop(shutdown_timeout, hpx::invalid_id, true);
1✔
1053
#else
1054
        HPX_UNUSED(shutdown_timeout);
1055
        HPX_UNUSED(localwait);
1056
        HPX_UNUSED(ec);
1057
#endif
1058

1059
        return 0;
1✔
1060
    }
1✔
1061

1062
    ///////////////////////////////////////////////////////////////////////////
1063
    void terminate()
×
1064
    {
1065
        if (!threads::get_self_ptr())
×
1066
        {
1067
            // hpx::terminate shouldn't be called from a non-HPX thread
1068
            std::terminate();
×
1069
        }
1070

1071
#if defined(HPX_HAVE_DISTRIBUTED_RUNTIME)
1072
        components::server::runtime_support* p =
×
1073
            static_cast<components::server::runtime_support*>(
×
1074
                get_runtime_distributed().get_runtime_support_lva());
×
1075

1076
        if (nullptr == p)
×
1077
        {
1078
            // the runtime system is not running, just terminate
1079
            std::terminate();
×
1080
        }
1081

1082
        p->terminate_all();
×
1083
#else
1084
        std::terminate();
1085
#endif
1086
    }
1087

1088
    ///////////////////////////////////////////////////////////////////////////
1089
    int stop(error_code& ec)
106✔
1090
    {
1091
        return hpx::local::stop(ec);
106✔
1092
    }
1093

1094
    ///////////////////////////////////////////////////////////////////////////
1095
    int suspend(error_code& ec)
101✔
1096
    {
1097
        return hpx::local::suspend(ec);
101✔
1098
    }
1099

1100
    ///////////////////////////////////////////////////////////////////////////
1101
    int resume(error_code& ec)
101✔
1102
    {
1103
        return hpx::local::resume(ec);
101✔
1104
    }
1105
}    // 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