• 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

67.51
/libs/full/runtime_distributed/src/server/runtime_support_server.cpp
1
//  Copyright (c) 2007-2016 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

10
#include <hpx/actions_base/plain_action.hpp>
11
#include <hpx/agas/addressing_service.hpp>
12
#include <hpx/assert.hpp>
13
#include <hpx/async_combinators/wait_all.hpp>
14
#include <hpx/async_distributed/continuation.hpp>
15
#include <hpx/command_line_handling/command_line_handling.hpp>
16
#include <hpx/command_line_handling/late_command_line_handling.hpp>
17
#include <hpx/command_line_handling/parse_command_line.hpp>
18
#include <hpx/components_base/agas_interface.hpp>
19
#include <hpx/components_base/component_type.hpp>
20
#include <hpx/components_base/server/create_component.hpp>
21
#include <hpx/execution_base/this_thread.hpp>
22
#include <hpx/futures/packaged_task.hpp>
23
#include <hpx/ini/ini.hpp>
24
#include <hpx/modules/async_distributed.hpp>
25
#include <hpx/modules/errors.hpp>
26
#include <hpx/modules/filesystem.hpp>
27
#include <hpx/modules/logging.hpp>
28
#include <hpx/modules/string_util.hpp>
29
#include <hpx/modules/threadmanager.hpp>
30
#include <hpx/modules/timing.hpp>
31
#include <hpx/performance_counters/counters.hpp>
32
#include <hpx/plugin_factories/binary_filter_factory_base.hpp>
33
#include <hpx/plugin_factories/message_handler_factory_base.hpp>
34
#include <hpx/prefix/find_prefix.hpp>
35
#include <hpx/runtime_components/console_logging.hpp>
36
#include <hpx/runtime_configuration/component_commandline_base.hpp>
37
#include <hpx/runtime_configuration/component_factory_base.hpp>
38
#include <hpx/runtime_configuration/static_factory_data.hpp>
39
#include <hpx/runtime_distributed.hpp>
40
#include <hpx/runtime_distributed/find_localities.hpp>
41
#include <hpx/runtime_distributed/runtime_fwd.hpp>
42
#include <hpx/runtime_distributed/server/runtime_support.hpp>
43
#include <hpx/runtime_distributed/stubs/runtime_support.hpp>
44
#include <hpx/runtime_local/component_startup_shutdown_base.hpp>
45
#include <hpx/runtime_local/runtime_local.hpp>
46
#include <hpx/runtime_local/shutdown_function.hpp>
47
#include <hpx/runtime_local/startup_function.hpp>
48
#include <hpx/serialization/serialize.hpp>
49
#include <hpx/serialization/vector.hpp>
50
#include <hpx/string_util/case_conv.hpp>
51
#include <hpx/thread_support/unlock_guard.hpp>
52
#include <hpx/type_support/unused.hpp>
53
#include <hpx/util/from_string.hpp>
54

55
#ifdef HPX_HAVE_LIB_MPI_BASE
56
#include <hpx/modules/mpi_base.hpp>
57
#endif
58

59
#include <algorithm>
60
#include <cstddef>
61
#include <cstdint>
62
#include <exception>
63
#include <iomanip>
64
#include <iostream>
65
#include <map>
66
#include <memory>
67
#include <mutex>
68
#include <set>
69
#include <sstream>
70
#include <string>
71
#include <system_error>
72
#include <thread>
73
#include <utility>
74
#include <vector>
75

76
///////////////////////////////////////////////////////////////////////////////
77
// Serialization support for the runtime_support actions
78
HPX_REGISTER_ACTION_ID(
5,792✔
79
    hpx::components::server::runtime_support::load_components_action,
80
    load_components_action, hpx::actions::load_components_action_id)
81
HPX_REGISTER_ACTION_ID(
4,636✔
82
    hpx::components::server::runtime_support::call_startup_functions_action,
83
    call_startup_functions_action,
84
    hpx::actions::call_startup_functions_action_id)
85
HPX_REGISTER_ACTION_ID(
7,643✔
86
    hpx::components::server::runtime_support::call_shutdown_functions_action,
87
    call_shutdown_functions_action,
88
    hpx::actions::call_shutdown_functions_action_id)
89
HPX_REGISTER_ACTION_ID(
5,195✔
90
    hpx::components::server::runtime_support::shutdown_action, shutdown_action,
91
    hpx::actions::shutdown_action_id)
92
HPX_REGISTER_ACTION_ID(
5,172✔
93
    hpx::components::server::runtime_support::shutdown_all_action,
94
    shutdown_all_action, hpx::actions::shutdown_all_action_id)
95
HPX_REGISTER_ACTION_ID(
4,636✔
96
    hpx::components::server::runtime_support::terminate_action,
97
    terminate_action, hpx::actions::terminate_action_id)
98
HPX_REGISTER_ACTION_ID(
4,636✔
99
    hpx::components::server::runtime_support::terminate_all_action,
100
    terminate_all_action, hpx::actions::terminate_all_action_id)
101
HPX_REGISTER_ACTION_ID(
4,636✔
102
    hpx::components::server::runtime_support::get_config_action,
103
    get_config_action, hpx::actions::get_config_action_id)
104
HPX_REGISTER_ACTION_ID(
4,875✔
105
    hpx::components::server::runtime_support::garbage_collect_action,
106
    garbage_collect_action, hpx::actions::garbage_collect_action_id)
107
HPX_REGISTER_ACTION_ID(
4,643✔
108
    hpx::components::server::runtime_support::create_performance_counter_action,
109
    create_performance_counter_action,
110
    hpx::actions::create_performance_counter_action_id)
111
HPX_REGISTER_ACTION_ID(hpx::components::server::runtime_support::
4,640✔
112
                           remove_from_connection_cache_action,
113
    remove_from_connection_cache_action,
114
    hpx::actions::remove_from_connection_cache_action_id)
115
#if defined(HPX_HAVE_NETWORKING)
116
HPX_REGISTER_ACTION_ID(
8,263✔
117
    hpx::components::server::runtime_support::dijkstra_termination_action,
118
    dijkstra_termination_action, hpx::actions::dijkstra_termination_action_id)
119
#endif
120

121
///////////////////////////////////////////////////////////////////////////////
122
HPX_DEFINE_COMPONENT_NAME(
×
123
    hpx::components::server::runtime_support, hpx_runtime_support)
124
HPX_DEFINE_GET_COMPONENT_TYPE_STATIC(hpx::components::server::runtime_support,
13,663✔
125
    hpx::components::component_runtime_support)
126

127
namespace hpx {
128
    // helper function to stop evaluating counters during shutdown
129
    void stop_evaluating_counters(bool terminate = false);
130
}    // namespace hpx
131

132
///////////////////////////////////////////////////////////////////////////////
133
namespace hpx { namespace components { namespace server {
134
    ///////////////////////////////////////////////////////////////////////////
135
    runtime_support::runtime_support(hpx::util::runtime_configuration& cfg)
1,186✔
136
      : stop_called_(false)
593✔
137
      , stop_done_(false)
593✔
138
      , terminated_(false)
593✔
139
      , main_thread_id_(std::this_thread::get_id())
593✔
140
      , shutdown_all_invoked_(false)
593✔
141
#if defined(HPX_HAVE_NETWORKING)
142
      , dijkstra_mtx_()
593✔
143
      , dijkstra_cond_()
593✔
144
      , dijkstra_color_(false)
593✔
145
#endif
146
      , p_mtx_()
593✔
147
      , plugins_()
593✔
148
      , modules_(cfg.modules())
593✔
149
      , static_modules_()
593✔
150
    {
151
    }
593✔
152

153
    // function to be called during shutdown
154
    // Action: shut down this runtime system instance
155
    void runtime_support::shutdown(
140✔
156
        double timeout, hpx::id_type const& respond_to)
157
    {
158
        // initiate system shutdown
159
        stop(timeout, respond_to, false);
140✔
160
    }
140✔
161

162
    // function to be called to terminate this locality immediately
163
    void runtime_support::terminate(hpx::id_type const& respond_to)
×
164
    {
165
#if !defined(HPX_COMPUTE_DEVICE_CODE)
166
        // push pending logs
167
        components::cleanup_logging();
×
168

169
        if (respond_to)
×
170
        {
171
            // respond synchronously
172
            using void_lco_type = lcos::base_lco_with_value<void>;
173
            using action_type = void_lco_type::set_event_action;
174

175
            naming::address addr;
×
176
            if (agas::is_local_address_cached(respond_to, addr))
×
177
            {
178
                // execute locally, action is executed immediately as it is
179
                // a direct_action
180
                hpx::detail::post_l<action_type>(respond_to, HPX_MOVE(addr));
×
181
            }
×
182
#if defined(HPX_HAVE_NETWORKING)
183
            else
184
            {
185
                // apply remotely, parcel is sent synchronously
186
                hpx::detail::post_r_sync<action_type>(
×
187
                    HPX_MOVE(addr), respond_to);
×
188
            }
189
#endif
190
        }
×
191
#else
192
        HPX_ASSERT(false);
193
        HPX_UNUSED(respond_to);
194
#endif
195
        std::abort();
×
196
    }
197
}}}    // namespace hpx::components::server
198

199
///////////////////////////////////////////////////////////////////////////////
200
namespace hpx { namespace components { namespace server {
201

202
    // initiate system shutdown for all localities
203
    void invoke_shutdown_functions(
902✔
204
        std::vector<hpx::id_type> const& localities, bool pre_shutdown)
205
    {
206
#if !defined(HPX_COMPUTE_DEVICE_CODE)
207
        std::vector<hpx::future<void>> results;
902✔
208
        results.reserve(localities.size());
902✔
209
        for (auto const& l : localities)
2,084✔
210
        {
211
            using call_shutdown_functions_action = hpx::components::server::
212
                runtime_support::call_shutdown_functions_action;
213
            results.push_back(
1,182✔
214
                hpx::async(call_shutdown_functions_action(), l, pre_shutdown));
1,182✔
215
        }
216
        hpx::wait_all(results);
902✔
217
#else
218
        HPX_ASSERT(false);
219
        HPX_UNUSED(localities);
220
        HPX_UNUSED(pre_shutdown);
221
#endif
222
    }
902✔
223

224
    ///////////////////////////////////////////////////////////////////////////
225
#if defined(HPX_HAVE_NETWORKING)
226
    void runtime_support::dijkstra_make_black()
458,267✔
227
    {
228
        // Rule 1: A machine sending a message makes itself black.
229
        std::lock_guard<dijkstra_mtx_type> l(dijkstra_mtx_);
458,267✔
230
        dijkstra_color_ = true;
458,267✔
231
    }
458,267✔
232

233
    void runtime_support::send_dijkstra_termination_token(
1,116✔
234
        std::uint32_t target_locality_id, std::uint32_t initiating_locality_id,
235
        std::uint32_t num_localities, bool dijkstra_token)
236
    {
237
        // First wait for this locality to become passive. We do this by
238
        // periodically checking the number of still running threads.
239
        //
240
        // Rule 0: When active, machine nr.i + 1 keeps the token; when passive,
241
        // it hands over the token to machine nr.i.
242
        threads::threadmanager& tm =
1,116✔
243
            hpx::applier::get_applier().get_thread_manager();
1,116✔
244

245
        tm.wait();
1,116✔
246
        tm.cleanup_terminated(true);
1,116✔
247

248
        // Now this locality has become passive, thus we can send the token
249
        // to the next locality.
250
        //
251
        // Rule 2: When machine nr.i + 1 propagates the probe, it hands over a
252
        // black token to machine nr.i if it is black itself, whereas while
253
        // being white it leaves the color of the token unchanged.
254
        {
255
            std::lock_guard<dijkstra_mtx_type> l(dijkstra_mtx_);
1,116✔
256
            if (dijkstra_color_)
1,116✔
257
                dijkstra_token = true;
291✔
258

259
            // Rule 5: Upon transmission of the token to machine nr.i, machine
260
            // nr.i + 1 becomes white.
261
            dijkstra_color_ = false;
1,116✔
262
        }
1,116✔
263

264
#if !defined(HPX_COMPUTE_DEVICE_CODE)
265
        hpx::id_type id(naming::get_id_from_locality_id(target_locality_id));
1,116✔
266
        hpx::post<dijkstra_termination_action>(
1,116✔
267
            id, initiating_locality_id, num_localities, dijkstra_token);
268
#else
269
        HPX_ASSERT(false);
270
        HPX_UNUSED(target_locality_id);
271
        HPX_UNUSED(initiating_locality_id);
272
        HPX_UNUSED(num_localities);
273
        HPX_UNUSED(dijkstra_token);
274
#endif
275
    }
1,116✔
276

277
    // invoked during termination detection
278
    void runtime_support::dijkstra_termination(
1,116✔
279
        std::uint32_t initiating_locality_id, std::uint32_t num_localities,
280
        bool dijkstra_token)
281
    {
282
        applier::applier& appl = hpx::applier::get_applier();
1,116✔
283
        naming::resolver_client& agas_client = naming::get_agas_client();
1,116✔
284

285
        agas_client.start_shutdown();
1,116✔
286

287
        parcelset::parcelhandler& ph = appl.get_parcel_handler();
1,116✔
288
        ph.flush_parcels();
1,116✔
289

290
        std::uint32_t locality_id = get_locality_id();
1,116✔
291

292
        if (initiating_locality_id == locality_id)
1,116✔
293
        {
294
            // we received the token after a full circle
295
            if (dijkstra_token)
556✔
296
            {
297
                std::lock_guard<dijkstra_mtx_type> l(dijkstra_mtx_);
278✔
298
                dijkstra_color_ = true;    // unsuccessful termination
278✔
299
            }
278✔
300

301
            dijkstra_cond_.notify_one();
556✔
302
            return;
556✔
303
        }
304

305
        if (0 == locality_id)
560✔
306
            locality_id = num_localities;
×
307

308
        send_dijkstra_termination_token(locality_id - 1, initiating_locality_id,
1,120✔
309
            num_localities, dijkstra_token);
560✔
310
    }
1,116✔
311
#endif
312

313
    // Kick off termination detection, this is modeled after Dijkstra's paper:
314
    // http://www.cs.mcgill.ca/~lli22/575/termination3.pdf.
315
    std::size_t runtime_support::dijkstra_termination_detection(
902✔
316
        std::vector<hpx::id_type> const& locality_ids)
317
    {
318
#if defined(HPX_HAVE_NETWORKING)
319
        std::uint32_t num_localities =
902✔
320
            static_cast<std::uint32_t>(locality_ids.size());
902✔
321
        if (num_localities == 1)
902✔
322
#endif
323

324
        {
325
            // While no real distributed termination detection has to be
326
            // performed, we should still wait for the thread-queues to drain.
327
            applier::applier& appl = hpx::applier::get_applier();
624✔
328
            threads::threadmanager& tm = appl.get_thread_manager();
624✔
329

330
            tm.wait();
624✔
331
            tm.cleanup_terminated(true);
624✔
332

333
            HPX_UNUSED(locality_ids);
624✔
334
            return 0;
624✔
335
        }
336

337
#if defined(HPX_HAVE_NETWORKING)
338
        std::uint32_t initiating_locality_id = get_locality_id();
278✔
339

340
        // send token to previous node
341
        std::uint32_t target_id = initiating_locality_id;
278✔
342
        if (0 == target_id)
278✔
343
            target_id = num_localities;
278✔
344

345
        std::size_t count = 0;    // keep track of number of trials
278✔
346

347
        {
348
            // Note: we protect the entire loop here since the stopping condition
349
            // depends on the shared variable "dijkstra_color_"
350
            // Proper unlocking for possible remote actions needs to be taken care of
351
            typedef std::unique_lock<dijkstra_mtx_type> dijkstra_scoped_lock;
352
            dijkstra_scoped_lock l(dijkstra_mtx_);
278✔
353
            do
278✔
354
            {
355
                LRT_(info).format(
556✔
356
                    "runtime_support::dijkstra_termination_detection: "
556✔
357
                    "initiates a probe by making itself white and sending a "
358
                    "white token to next machine.");
359

360
                // Rule 4: Machine nr.0 initiates a probe by making itself white
361
                // and sending a white token to machine nr.N - 1.
362
                dijkstra_color_ = false;    // start off with white
556✔
363

364
                {
365
                    unlock_guard<dijkstra_scoped_lock> ul(l);
556✔
366
                    send_dijkstra_termination_token(target_id - 1,
1,112✔
367
                        initiating_locality_id, num_localities,
556✔
368
                        dijkstra_color_);
556✔
369
                }
556✔
370

371
                LRT_(info).format(
556✔
372
                    "runtime_support::dijkstra_termination_detection: "
556✔
373
                    "wait for token to come back to us.");
374

375
                // wait for token to come back to us
376
                dijkstra_cond_.wait(l);
556✔
377

378
                // Rule 3: After the completion of an unsuccessful probe, machine
379
                // nr.0 initiates a next probe.
380

381
                ++count;
556✔
382

383
                if (dijkstra_color_)
556✔
384
                {
385
                    LRT_(info).format(
278✔
386
                        "runtime_support::dijkstra_termination_detection: "
278✔
387
                        "After the completion of an unsuccessful probe, "
388
                        "initiate next probe.");
389
                }
278✔
390

391
            } while (dijkstra_color_);
556✔
392
        }
278✔
393

394
        return count;
278✔
395
#endif
396
    }
902✔
397

398
    ///////////////////////////////////////////////////////////////////////////
399
    void runtime_support::shutdown_all(double timeout)
478✔
400
    {
401
        if (find_here() != hpx::find_root_locality())
478✔
402
        {
403
            HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
404
                "runtime_support::shutdown_all",
405
                "shutdown_all should be invoked on the root locality only");
406
            return;
407
        }
408

409
        // make sure shutdown_all is invoked only once
410
        bool flag = false;
478✔
411
        if (!shutdown_all_invoked_.compare_exchange_strong(flag, true))
478✔
412
        {
413
            return;
27✔
414
        }
415

416
        LRT_(info).format(
451✔
417
            "runtime_support::shutdown_all: initializing application shutdown");
437✔
418

419
        applier::applier& appl = hpx::applier::get_applier();
451✔
420
        naming::resolver_client& agas_client = naming::get_agas_client();
451✔
421

422
        agas_client.start_shutdown();
451✔
423

424
        stop_evaluating_counters(true);
451✔
425

426
        // wake up suspended pus
427
        threads::threadmanager& tm = appl.get_thread_manager();
451✔
428
        tm.resume();
451✔
429

430
        std::vector<hpx::id_type> locality_ids = find_all_localities();
451✔
431
        std::size_t count = dijkstra_termination_detection(locality_ids);
451✔
432

433
        LRT_(info).format("runtime_support::shutdown_all: passed first "
451✔
434
                          "termination detection (count: {}).",
435
            count);
436

437
        // execute registered shutdown functions on all localities
438
        invoke_shutdown_functions(locality_ids, true);
451✔
439
        invoke_shutdown_functions(locality_ids, false);
451✔
440

441
        LRT_(info).format(
451✔
442
            "runtime_support::shutdown_all: invoked shutdown functions");
437✔
443

444
        // Do a second round of termination detection to synchronize with all
445
        // work that was triggered by the invocation of the shutdown
446
        // functions.
447
        count = dijkstra_termination_detection(locality_ids);
451✔
448

449
        LRT_(info).format("runtime_support::shutdown_all: passed second "
451✔
450
                          "termination detection (count: {}).",
451
            count);
452

453
        // Shut down all localities except the local one, we can't use
454
        // broadcast here as we have to handle the back parcel in a special
455
        // way.
456
        std::reverse(locality_ids.begin(), locality_ids.end());
451✔
457
        std::uint32_t locality_id = get_locality_id();
451✔
458
        std::vector<hpx::future<void>> lazy_actions;
451✔
459

460
        for (hpx::id_type const& id : locality_ids)
1,042✔
461
        {
462
            if (locality_id != naming::get_locality_id_from_id(id))
591✔
463
            {
464
                using components::stubs::runtime_support;
465
                lazy_actions.push_back(
140✔
466
                    runtime_support::shutdown_async(id, timeout));
140✔
467
            }
140✔
468
        }
469

470
        // wait for all localities to be stopped
471
        hpx::wait_all(lazy_actions);
451✔
472

473
        LRT_(info).format("runtime_support::shutdown_all: all localities have "
451✔
474
                          "been shut down");
475

476
        // Now make sure this local locality gets shut down as well.
477
        // There is no need to respond...
478
        stop(timeout, hpx::invalid_id, false);
451✔
479
    }
478✔
480

481
    ///////////////////////////////////////////////////////////////////////////
482
    // initiate system shutdown for all localities
483
    void runtime_support::terminate_all()
×
484
    {
485
        std::vector<naming::gid_type> locality_ids;
×
486
        naming::get_agas_client().get_localities(locality_ids);
×
487
        std::reverse(locality_ids.begin(), locality_ids.end());
×
488

489
        // Terminate all localities except the local one, we can't use
490
        // broadcast here as we have to handle the back parcel in a special
491
        // way.
492
        {
493
            std::uint32_t locality_id = get_locality_id();
×
494
            std::vector<hpx::future<void>> lazy_actions;
×
495

496
            for (naming::gid_type gid : locality_ids)
×
497
            {
498
                if (locality_id != naming::get_locality_id_from_gid(gid))
×
499
                {
500
                    using components::stubs::runtime_support;
501
                    hpx::id_type id(
×
502
                        gid, hpx::id_type::management_type::unmanaged);
503
                    lazy_actions.push_back(
×
504
                        runtime_support::terminate_async(id));
×
505
                }
×
506
            }
507

508
            // wait for all localities to be stopped
509
            hpx::wait_all(lazy_actions);
×
510
        }
×
511

512
        // now make sure this local locality gets terminated as well.
513
        terminate(hpx::invalid_id);    //good night
×
514
    }
×
515

516
    ///////////////////////////////////////////////////////////////////////////
517
    // Retrieve configuration information
518
    util::section runtime_support::get_config()
×
519
    {
520
        return *(get_runtime().get_config().get_section("application"));
×
521
    }
×
522

523
    ///////////////////////////////////////////////////////////////////////////
524
    /// \brief Force a garbage collection operation in the AGAS layer.
525
    void runtime_support::garbage_collect()
92✔
526
    {
527
        naming::get_agas_client().garbage_collect_non_blocking();
92✔
528
    }
92✔
529

530
    ///////////////////////////////////////////////////////////////////////////
531
    /// \brief Create the given performance counter instance.
532
    naming::gid_type runtime_support::create_performance_counter(
63✔
533
        performance_counters::counter_info const& info)
534
    {
535
        return performance_counters::detail::create_counter_local(info);
63✔
536
    }
537

538
    ///////////////////////////////////////////////////////////////////////////
539
    void runtime_support::delete_function_lists()
591✔
540
    {
541
        pre_startup_functions_.clear();
591✔
542
        startup_functions_.clear();
591✔
543
        pre_shutdown_functions_.clear();
591✔
544
        shutdown_functions_.clear();
591✔
545
    }
591✔
546

547
    void runtime_support::tidy()
1,182✔
548
    {
549
        // Only after releasing the components we are allowed to release
550
        // the modules. This is done in reverse order of loading.
551
        plugins_.clear();    // unload all plugins
1,182✔
552
        modules_.clear();    // unload all modules
1,182✔
553
    }
1,182✔
554

555
    ///////////////////////////////////////////////////////////////////////////
556
    /// \brief Remove the given locality from our connection cache
557
    void runtime_support::remove_from_connection_cache(
1✔
558
        naming::gid_type const& gid, parcelset::endpoints_type const& eps)
559
    {
560
        runtime_distributed* rt = get_runtime_distributed_ptr();
1✔
561
        if (rt == nullptr)
1✔
562
            return;
×
563

564
#if defined(HPX_HAVE_NETWORKING)
565
        // instruct our connection cache to drop all connections it is holding
566
        rt->get_parcel_handler().remove_from_connection_cache(gid, eps);
1✔
567
#else
568
        HPX_UNUSED(gid);
569
        HPX_UNUSED(eps);
570
#endif
571
    }
1✔
572

573
    ///////////////////////////////////////////////////////////////////////////
574
    void runtime_support::run()
593✔
575
    {
576
        std::unique_lock<std::mutex> l(mtx_);
593✔
577
        stop_called_ = false;
593✔
578
        stop_done_ = false;
593✔
579
        terminated_ = false;
593✔
580
        shutdown_all_invoked_.store(false);
593✔
581
    }
593✔
582

583
    void runtime_support::wait()
593✔
584
    {
585
        std::unique_lock<std::mutex> l(mtx_);
593✔
586
        while (!stop_done_)
1,180✔
587
        {
588
            LRT_(info).format("runtime_support: about to enter wait state");
588✔
589
            wait_condition_.wait(l);
587✔
590
            LRT_(info).format("runtime_support: exiting wait state");
588✔
591
        }
592
    }
592✔
593

594
    void runtime_support::stop(double timeout, hpx::id_type const& respond_to,
592✔
595
        bool remove_from_remote_caches)
596
    {
597
        std::unique_lock<std::mutex> l(mtx_);
592✔
598
        if (!stop_called_)
592✔
599
        {
600
            // push pending logs
601
            components::cleanup_logging();
592✔
602

603
            HPX_ASSERT(!terminated_);
592✔
604

605
            applier::applier& appl = hpx::applier::get_applier();
592✔
606
            threads::threadmanager& tm = appl.get_thread_manager();
592✔
607
            naming::resolver_client& agas_client = naming::get_agas_client();
592✔
608

609
            error_code ec(throwmode::lightweight);
592✔
610

611
            stop_called_ = true;
592✔
612

613
            {
614
                unlock_guard<std::mutex> ul(mtx_);
592✔
615

616
                util::runtime_configuration& cfg = get_runtime().get_config();
592✔
617
                std::size_t shutdown_check_count =
592✔
618
                    util::get_entry_as<std::size_t>(
592✔
619
                        cfg, "hpx.shutdown_check_count", 10);
592✔
620
                bool success = util::detail::yield_while_count_timeout(
592✔
621
                    [&tm] {
7,275✔
622
                        tm.cleanup_terminated(true);
6,683✔
623
                        return tm.is_busy();
6,683✔
624
                    },
625
                    shutdown_check_count,
592✔
626
                    std::chrono::duration<double>(timeout),
592✔
627
                    "runtime_support::stop");
628

629
                // If it took longer than expected, kill all suspended threads as
630
                // well.
631
                if (!success)
592✔
632
                {
633
                    // now we have to wait for all threads to be aborted
634
                    success = util::detail::yield_while_count_timeout(
×
635
                        [&tm] {
×
636
                            tm.abort_all_suspended_threads();
×
637
                            tm.cleanup_terminated(true);
×
638
                            return tm.is_busy();
×
639
                        },
640
                        shutdown_check_count,
×
641
                        std::chrono::duration<double>(timeout),
×
642
                        "runtime_support::stop");
643
                    HPX_UNUSED(success);
×
644
                }
×
645

646
                // Drop the locality from the partition table.
647
                naming::gid_type here = agas_client.get_local_locality();
592✔
648

649
                // unregister fixed components
650
                agas_client.unbind_local(
592✔
651
                    appl.get_runtime_support_raw_gid(), ec);
592✔
652

653
                if (remove_from_remote_caches)
592✔
654
                    remove_here_from_connection_cache();
1✔
655

656
                agas_client.unregister_locality(here, ec);
592✔
657

658
                if (remove_from_remote_caches)
592✔
659
                    remove_here_from_console_connection_cache();
1✔
660

661
                if (respond_to)
592✔
662
                {
663
#if !defined(HPX_COMPUTE_DEVICE_CODE)
664
#if defined(HPX_HAVE_NETWORKING)
665
                    // respond synchronously
666
                    using void_lco_type = lcos::base_lco_with_value<void>;
667
                    using action_type = void_lco_type::set_event_action;
668
#endif
669
#else
670
                    HPX_ASSERT(false);
671
#endif
672

673
                    naming::address addr;
140✔
674
                    if (agas::is_local_address_cached(respond_to, addr))
140✔
675
                    {
676
                        // this should never happen
677
                        HPX_ASSERT(false);
×
678
                    }
×
679
#if defined(HPX_HAVE_NETWORKING)
680
                    else
681
                    {
682
#if !defined(HPX_COMPUTE_DEVICE_CODE)
683
                        // apply remotely, parcel is sent synchronously
684
                        hpx::detail::post_r_sync<action_type>(
140✔
685
                            HPX_MOVE(addr), respond_to);
140✔
686
#else
687
                        HPX_ASSERT(false);
688
#endif
689
                    }
690
#endif
691
                }
140✔
692
            }
592✔
693

694
            stop_done_ = true;
592✔
695
            wait_condition_.notify_all();
592✔
696

697
            // The main thread notifies stop_condition_, so don't wait if we're
698
            // on the main thread.
699
            if (std::this_thread::get_id() != main_thread_id_)
592✔
700
            {
701
                stop_condition_.wait(l);    // wait for termination
592✔
702
            }
592✔
703
        }
592✔
704
    }
592✔
705

706
    void runtime_support::notify_waiting_main()
×
707
    {
708
        std::unique_lock<std::mutex> l(mtx_);
×
709
        if (!stop_called_)
×
710
        {
711
            stop_called_ = true;
×
712
            stop_done_ = true;
×
713
            wait_condition_.notify_all();
×
714

715
            // The main thread notifies stop_condition_, so don't wait if we're
716
            // on the main thread.
717
            if (std::this_thread::get_id() != main_thread_id_)
×
718
            {
719
                stop_condition_.wait(l);    // wait for termination
×
720
            }
×
721
        }
×
722
    }
×
723

724
    // this will be called after the thread manager has exited
725
    void runtime_support::stopped()
592✔
726
    {
727
        std::lock_guard<std::mutex> l(mtx_);
592✔
728
        if (!terminated_)
592✔
729
        {
730
            terminated_ = true;
592✔
731
            stop_condition_.notify_all();    // finished cleanup/termination
592✔
732
        }
592✔
733
    }
592✔
734

735
#if defined(HPX_HAVE_NETWORKING)
736
    namespace detail {
737
        void handle_list_parcelports()
×
738
        {
739
            // make sure all output is kept together
740
            std::ostringstream strm;
×
741
            strm << std::string(79, '*') << '\n';
×
742
            strm << "locality: " << hpx::get_locality_id() << '\n';
×
743

744
            get_runtime_distributed().get_parcel_handler().list_parcelports(
×
745
                strm);
746

747
            std::cout << strm.str();
×
748
        }
×
749
    }    // namespace detail
750
#endif
751

752
    ///////////////////////////////////////////////////////////////////////////
753
    int runtime_support::load_components()
593✔
754
    {
755
        // load components now that AGAS is up
756
        util::runtime_configuration& ini = get_runtime().get_config();
593✔
757

758
        // first static components
759
        ini.load_components_static(components::get_static_module_data());
593✔
760

761
        // modules loaded dynamically should not register themselves statically
762
        components::get_initial_static_loading() = false;
593✔
763

764
        // make sure every component module gets asked for startup/shutdown
765
        // functions only once
766
        std::set<std::string> startup_handled;
593✔
767

768
        // collect additional command-line options
769
        hpx::program_options::options_description options;
593✔
770

771
        // then dynamic ones
772
        naming::resolver_client& client = naming::get_agas_client();
593✔
773
        int result = load_components(
593✔
774
            ini, client.get_local_locality(), client, options, startup_handled);
593✔
775
        if (result != 0)
593✔
776
        {
777
            return result;
×
778
        }
779

780
        if (!load_plugins(ini, options, startup_handled))
593✔
781
        {
782
            return -2;
×
783
        }
784

785
#if defined(HPX_HAVE_NETWORKING)
786
        return util::handle_late_commandline_options(ini, options,
593✔
787
            &hpx::detail::handle_print_bind, &detail::handle_list_parcelports);
788
#else
789
        return util::handle_late_commandline_options(
790
            ini, options, &hpx::detail::handle_print_bind);
791
#endif
792
    }
593✔
793

794
    void runtime_support::call_startup_functions(bool pre_startup)
1,186✔
795
    {
796
        if (pre_startup)
1,186✔
797
        {
798
            get_runtime().set_state(hpx::state::pre_startup);
593✔
799
            for (startup_function_type& f : pre_startup_functions_)
2,426✔
800
            {
801
                f();
1,833✔
802
            }
803
        }
593✔
804
        else
805
        {
806
            get_runtime().set_state(hpx::state::startup);
593✔
807
            for (startup_function_type& f : startup_functions_)
1,178✔
808
            {
809
                f();
585✔
810
            }
811
        }
812
    }
1,186✔
813

814
    void runtime_support::call_shutdown_functions(bool pre_shutdown)
1,184✔
815
    {
816
        runtime& rt = get_runtime();
1,184✔
817
        if (pre_shutdown)
1,184✔
818
        {
819
            rt.set_state(hpx::state::pre_shutdown);
592✔
820
            for (shutdown_function_type& f : pre_shutdown_functions_)
1,186✔
821
            {
822
                try
823
                {
824
                    f();
594✔
825
                }
594✔
826
                catch (...)
827
                {
828
                    rt.report_error(std::current_exception());
×
829
                }
×
830
            }
831
        }
592✔
832
        else
833
        {
834
            rt.set_state(hpx::state::shutdown);
592✔
835
            for (shutdown_function_type& f : shutdown_functions_)
73,744✔
836
            {
837
                try
838
                {
839
                    f();
73,152✔
840
                }
73,152✔
841
                catch (...)
842
                {
843
                    rt.report_error(std::current_exception());
×
844
                }
×
845
            }
846
        }
847
    }
1,184✔
848

849
    // working around non-copy-ability of packaged_task
850
    struct indirect_packaged_task
3✔
851
    {
852
        typedef hpx::packaged_task<void()> packaged_task_type;
853

854
        indirect_packaged_task()
1✔
855
          : pt(std::make_shared<packaged_task_type>([]() {}))
2✔
856
        {
857
        }
1✔
858

859
        hpx::future<void> get_future()
1✔
860
        {
861
            return pt->get_future();
1✔
862
        }
863

864
        template <typename... Ts>
865
        void operator()(Ts&&... /* vs */)
1✔
866
        {
867
            // This needs to be run on a HPX thread
868
            hpx::post(HPX_MOVE(*pt));
1✔
869
            pt.reset();
1✔
870
        }
1✔
871

872
        std::shared_ptr<packaged_task_type> pt;
873
    };
874

875
    void runtime_support::remove_here_from_connection_cache()
1✔
876
    {
877
#if !defined(HPX_COMPUTE_DEVICE_CODE)
878
#if defined(HPX_HAVE_NETWORKING)
879
        runtime_distributed* rtd = get_runtime_distributed_ptr();
1✔
880
        if (rtd == nullptr)
1✔
881
            return;
×
882

883
        std::vector<hpx::id_type> locality_ids = find_remote_localities();
1✔
884

885
        typedef server::runtime_support::remove_from_connection_cache_action
886
            action_type;
887

888
        std::vector<future<void>> callbacks;
1✔
889
        callbacks.reserve(locality_ids.size());
1✔
890

891
        action_type act;
892
        for (hpx::id_type const& id : locality_ids)
2✔
893
        {
894
            // console is handled separately
895
            if (naming::get_locality_id_from_id(id) == 0)
1✔
896
                continue;
1✔
897

898
            indirect_packaged_task ipt;
×
899
            callbacks.push_back(ipt.get_future());
×
900
            hpx::post_cb(
×
901
                act, id, HPX_MOVE(ipt), agas::get_locality(), rtd->endpoints());
×
902
        }
×
903

904
        hpx::wait_all(callbacks);
1✔
905
#endif
906
#else
907
        HPX_ASSERT(false);
908
#endif
909
    }
1✔
910

911
    void runtime_support::remove_here_from_console_connection_cache()
1✔
912
    {
913
#if !defined(HPX_COMPUTE_DEVICE_CODE)
914
#if defined(HPX_HAVE_NETWORKING)
915
        runtime_distributed* rtd = get_runtime_distributed_ptr();
1✔
916
        if (rtd == nullptr)
1✔
917
            return;
×
918

919
        typedef server::runtime_support::remove_from_connection_cache_action
920
            action_type;
921

922
        action_type act;
923
        indirect_packaged_task ipt;
1✔
924
        future<void> callback = ipt.get_future();
1✔
925

926
        // handle console separately
927
        id_type id = naming::get_id_from_locality_id(0);
1✔
928
        hpx::post_cb(
1✔
929
            act, id, HPX_MOVE(ipt), agas::get_locality(), rtd->endpoints());
1✔
930

931
        callback.wait();
1✔
932
#endif
933
#else
934
        HPX_ASSERT(false);
935
#endif
936
    }
1✔
937

938
    ///////////////////////////////////////////////////////////////////////////
939
#if defined(HPX_HAVE_NETWORKING)
940
    void runtime_support::register_message_handler(
20,171✔
941
        char const* message_handler_type, char const* action, error_code& ec)
942
    {
943
        // locate the factory for the requested plugin type
944
        typedef std::unique_lock<plugin_map_mutex_type> plugin_map_scoped_lock;
945
        plugin_map_scoped_lock l(p_mtx_);
20,171✔
946

947
        plugin_map_type::const_iterator it =
948
            plugins_.find(message_handler_type);
20,171✔
949
        if (it == plugins_.end() || !(*it).second.first)
20,171✔
950
        {
951
            l.unlock();
408✔
952
            if (ec.category() != hpx::get_lightweight_hpx_category())
408✔
953
            {
954
                // we don't know anything about this component
955
                HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
956
                    "runtime_support::create_message_handler",
957
                    "attempt to create message handler plugin instance of "
958
                    "invalid/unknown type: {}",
959
                    message_handler_type);
960
            }
×
961
            else
962
            {
963
                // lightweight error handling
964
                HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
408✔
965
                    "runtime_support::create_message_handler",
966
                    "attempt to create message handler plugin instance of "
967
                    "invalid/unknown type");
968
            }
969
            return;
408✔
970
        }
971

972
        l.unlock();
19,763✔
973

974
        // create new component instance
975
        std::shared_ptr<plugins::message_handler_factory_base> factory(
976
            std::static_pointer_cast<plugins::message_handler_factory_base>(
19,763✔
977
                (*it).second.first));
19,763✔
978

979
        factory->register_action(action, ec);
19,763✔
980

981
        if (ec)
19,763✔
982
        {
983
            HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
984
                "runtime_support::register_message_handler",
985
                "couldn't register action '{}' for message handler plugin of "
986
                "type: {}",
987
                action, message_handler_type);
988
            return;
×
989
        }
990

991
        if (&ec != &throws)
19,763✔
992
            ec = make_success_code();
19,763✔
993

994
        // log result if requested
995
        LRT_(info).format(
19,763✔
996
            "successfully registered message handler plugin of type: {}",
19,661✔
997
            message_handler_type);
998
    }
20,171✔
999

1000
    parcelset::policies::message_handler*
1001
    runtime_support::create_message_handler(char const* message_handler_type,
285✔
1002
        char const* action, parcelset::parcelport* pp, std::size_t num_messages,
1003
        std::size_t interval, error_code& ec)
1004
    {
1005
        // locate the factory for the requested plugin type
1006
        typedef std::unique_lock<plugin_map_mutex_type> plugin_map_scoped_lock;
1007
        plugin_map_scoped_lock l(p_mtx_);
285✔
1008

1009
        plugin_map_type::const_iterator it =
1010
            plugins_.find(message_handler_type);
285✔
1011
        if (it == plugins_.end() || !(*it).second.first)
285✔
1012
        {
1013
            l.unlock();
×
1014
            if (ec.category() != hpx::get_lightweight_hpx_category())
×
1015
            {
1016
                // we don't know anything about this component
1017
                HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
1018
                    "runtime_support::create_message_handler",
1019
                    "attempt to create message handler plugin instance of "
1020
                    "invalid/unknown type: {}",
1021
                    message_handler_type);
1022
            }
×
1023
            else
1024
            {
1025
                // lightweight error handling
1026
                HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
1027
                    "runtime_support::create_message_handler",
1028
                    "attempt to create message handler plugin instance of "
1029
                    "invalid/unknown type");
1030
            }
1031
            return nullptr;
×
1032
        }
1033

1034
        l.unlock();
285✔
1035

1036
        // create new component instance
1037
        std::shared_ptr<plugins::message_handler_factory_base> factory(
1038
            std::static_pointer_cast<plugins::message_handler_factory_base>(
285✔
1039
                (*it).second.first));
285✔
1040

1041
        parcelset::policies::message_handler* mh =
285✔
1042
            factory->create(action, pp, num_messages, interval);
285✔
1043
        if (nullptr == mh)
285✔
1044
        {
1045
            HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
1046
                "runtime_support::create_message_handler",
1047
                "couldn't create message handler plugin of type: {}",
1048
                message_handler_type);
1049
            return nullptr;
×
1050
        }
1051

1052
        if (&ec != &throws)
285✔
1053
            ec = make_success_code();
283✔
1054

1055
        // log result if requested
1056
        LRT_(info).format(
285✔
1057
            "successfully created message handler plugin of type: {}",
284✔
1058
            message_handler_type);
1059
        return mh;
285✔
1060
    }
285✔
1061

1062
    serialization::binary_filter* runtime_support::create_binary_filter(
×
1063
        char const* binary_filter_type, bool compress,
1064
        serialization::binary_filter* next_filter, error_code& ec)
1065
    {
1066
        // locate the factory for the requested plugin type
1067
        typedef std::unique_lock<plugin_map_mutex_type> plugin_map_scoped_lock;
1068
        plugin_map_scoped_lock l(p_mtx_);
×
1069

1070
        plugin_map_type::const_iterator it = plugins_.find(binary_filter_type);
×
1071
        if (it == plugins_.end() || !(*it).second.first)
×
1072
        {
1073
            l.unlock();
×
1074
            // we don't know anything about this component
1075
            HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
1076
                "runtime_support::create_binary_filter",
1077
                "attempt to create binary filter plugin instance of "
1078
                "invalid/unknown type: {}",
1079
                binary_filter_type);
1080
            return nullptr;
×
1081
        }
1082

1083
        l.unlock();
×
1084

1085
        // create new component instance
1086
        std::shared_ptr<plugins::binary_filter_factory_base> factory(
1087
            std::static_pointer_cast<plugins::binary_filter_factory_base>(
×
1088
                (*it).second.first));
×
1089

1090
        serialization::binary_filter* bf =
×
1091
            factory->create(compress, next_filter);
×
1092
        if (nullptr == bf)
×
1093
        {
1094
            HPX_THROWS_IF(ec, hpx::error::bad_plugin_type,
×
1095
                "runtime_support::create_binary_filter",
1096
                "couldn't create binary filter plugin of type: {}",
1097
                binary_filter_type);
1098
            return nullptr;
×
1099
        }
1100

1101
        if (&ec != &throws)
×
1102
            ec = make_success_code();
×
1103

1104
        // log result if requested
1105
        LRT_(info).format(
×
1106
            "successfully created binary filter handler plugin of type: {}",
×
1107
            binary_filter_type);
1108
        return bf;
×
1109
    }
×
1110
#endif
1111

1112
    ///////////////////////////////////////////////////////////////////////////
1113
    bool runtime_support::load_component_static(util::section& ini,
16,209✔
1114
        std::string const& instance, std::string const& component,
1115
        filesystem::path const& lib, naming::gid_type const& /* prefix */,
1116
        naming::resolver_client& /* agas_client */, bool /* isdefault */,
1117
        bool /* isenabled */,
1118
        hpx::program_options::options_description& options,
1119
        std::set<std::string>& startup_handled)
1120
    {
1121
        try
1122
        {
1123
            // initialize the factory instance using the preferences from the
1124
            // ini files
1125
            util::section const* component_ini = nullptr;
16,209✔
1126
            std::string component_section("hpx.components." + instance);
16,209✔
1127
            if (ini.has_section(component_section))
16,209✔
1128
                component_ini = ini.get_section(component_section);
16,209✔
1129

1130
            if (nullptr == component_ini ||
32,418✔
1131
                "0" == component_ini->get_entry("no_factory", "0"))
16,209✔
1132
            {
1133
                util::plugin::get_plugins_list_type f;
1134
                if (!components::get_static_factory(instance, f))
16,209✔
1135
                {
1136
                    LRT_(warning).format(
×
1137
                        "static loading failed: {}: {}: couldn't find factory "
×
1138
                        "in global static factory map",
1139
                        lib.string(), instance);
×
1140
                    return false;
×
1141
                }
1142

1143
                LRT_(info).format(
16,209✔
1144
                    "static loading succeeded: {}: {}", lib.string(), instance);
15,802✔
1145
            }
16,209✔
1146

1147
            // make sure startup/shutdown registration is called once for each
1148
            // module, same for plugins
1149
            if (startup_handled.find(component) == startup_handled.end())
16,209✔
1150
            {
1151
                error_code ec(throwmode::lightweight);
844✔
1152
                startup_handled.insert(component);
844✔
1153
                load_commandline_options_static(component, options, ec);
844✔
1154
                if (ec)
844✔
1155
                    ec = error_code(throwmode::lightweight);
×
1156
                load_startup_shutdown_functions_static(component, ec);
844✔
1157
            }
844✔
1158
        }
16,209✔
1159
        catch (hpx::exception const&)
1160
        {
1161
            throw;
×
1162
        }
×
1163
        catch (std::logic_error const& e)
1164
        {
1165
            LRT_(warning).format("static loading failed: {}: {}: {}",
×
1166
                lib.string(), instance, e.what());
×
1167
            return false;
×
1168
        }
×
1169
        catch (std::exception const& e)
1170
        {
1171
            LRT_(warning).format("static loading failed: {}: {}: {}",
×
1172
                lib.string(), instance, e.what());
×
1173
            return false;
×
1174
        }
×
1175
        return true;    // component got loaded
16,209✔
1176
    }
16,209✔
1177

1178
    ///////////////////////////////////////////////////////////////////////////
1179
    // Load all components from the ini files found in the configuration
1180
    int runtime_support::load_components(util::section& ini,
593✔
1181
        naming::gid_type const& prefix, naming::resolver_client& agas_client,
1182
        hpx::program_options::options_description& options,
1183
        std::set<std::string>& startup_handled)
1184
    {
1185
        // load all components as described in the configuration information
1186
        if (!ini.has_section("hpx.components"))
593✔
1187
        {
1188
            LRT_(info).format(
×
1189
                "No components found/loaded, HPX will be mostly non-functional "
×
1190
                "(no section [hpx.components] found).");
1191
            return 0;    // no components to load
×
1192
        }
1193

1194
        // each shared library containing components may have an ini section
1195
        //
1196
        // # mandatory section describing the component module
1197
        // [hpx.components.instance_name]
1198
        //  name = ...           # the name of this component module
1199
        //  path = ...           # the path where to find this component module
1200
        //  enabled = false      # optional (default is assumed to be true)
1201
        //  static = false       # optional (default is assumed to be false)
1202
        //
1203
        // # optional section defining additional properties for this module
1204
        // [hpx.components.instance_name.settings]
1205
        //  key = value
1206
        //
1207
        util::section* sec = ini.get_section("hpx.components");
593✔
1208
        if (nullptr == sec)
593✔
1209
        {
1210
            LRT_(error).format("nullptr section found");
×
1211
            return 0;    // something bad happened
×
1212
        }
1213

1214
        util::section::section_map const& s = (*sec).get_sections();
593✔
1215
        typedef util::section::section_map::const_iterator iterator;
1216
        iterator end = s.end();
593✔
1217
        for (iterator i = s.begin(); i != end; ++i)
19,138✔
1218
        {
1219
            namespace fs = filesystem;
1220

1221
            // the section name is the instance name of the component
1222
            util::section const& sect = i->second;
18,545✔
1223
            std::string instance(sect.get_name());
18,545✔
1224
            std::string component;
18,545✔
1225

1226
            if (sect.has_entry("name"))
18,545✔
1227
                component = sect.get_entry("name");
18,545✔
1228
            else
1229
                component = instance;
×
1230

1231
            bool isenabled = true;
18,545✔
1232
            if (sect.has_entry("enabled"))
18,545✔
1233
            {
1234
                std::string tmp = sect.get_entry("enabled");
18,545✔
1235
                hpx::string_util::to_lower(tmp);
18,545✔
1236
                if (tmp == "no" || tmp == "false" || tmp == "0")
18,545✔
1237
                {
1238
                    LRT_(info).format(
2✔
1239
                        "component factory disabled: {}", instance);
2✔
1240
                    isenabled = false;    // this component has been disabled
2✔
1241
                }
2✔
1242
            }
18,545✔
1243

1244
            // test whether this component section was generated
1245
            bool isdefault = false;
18,545✔
1246
            if (sect.has_entry("isdefault"))
18,545✔
1247
            {
1248
                std::string tmp = sect.get_entry("isdefault");
×
1249
                hpx::string_util::to_lower(tmp);
×
1250
                if (tmp == "true")
×
1251
                    isdefault = true;
×
1252
            }
×
1253

1254
            fs::path lib;
18,545✔
1255
            try
1256
            {
1257
                std::string component_path;
18,545✔
1258
                if (sect.has_entry("path"))
18,545✔
1259
                    component_path = sect.get_entry("path");
4,708✔
1260
                else
1261
                    component_path = HPX_DEFAULT_COMPONENT_PATH;
13,837✔
1262

1263
                hpx::string_util::char_separator sep(HPX_INI_PATH_DELIMITER);
18,545✔
1264
                hpx::string_util::tokenizer tokens(component_path, sep);
18,545✔
1265
                std::error_code fsec;
18,545✔
1266
                for (auto it = tokens.begin(); it != tokens.end(); ++it)
35,549✔
1267
                {
1268
                    lib = fs::path(*it);
17,004✔
1269
                    fs::path lib_path =
1270
                        lib / std::string(HPX_MAKE_DLL_STRING(component));
17,004✔
1271
                    if (fs::exists(lib_path, fsec))
17,004✔
1272
                    {
1273
                        break;
1,743✔
1274
                    }
1275
                    lib.clear();
15,261✔
1276
                }
17,004✔
1277

1278
                if (sect.get_entry("static", "0") == "1")
18,545✔
1279
                {
1280
                    load_component_static(ini, instance, component, lib, prefix,
32,418✔
1281
                        agas_client, isdefault, isenabled, options,
16,209✔
1282
                        startup_handled);
16,209✔
1283
                }
16,209✔
1284
                else
1285
                {
1286
#if defined(HPX_HAVE_STATIC_LINKING)
1287
                    HPX_THROW_EXCEPTION(hpx::error::service_unavailable,
1288
                        "runtime_support::load_components",
1289
                        "static linking configuration does not support dynamic "
1290
                        "loading of component '{}'",
1291
                        instance);
1292
#else
1293
                    load_component_dynamic(ini, instance, component, lib,
2,336✔
1294
                        prefix, agas_client, isdefault, isenabled, options,
2,336✔
1295
                        startup_handled);
2,336✔
1296
#endif
1297
                }
1298
            }
18,545✔
1299
            catch (hpx::exception const& e)
1300
            {
1301
                LRT_(warning).format(
×
1302
                    "caught exception while loading {}, {}: {}", instance,
×
1303
                    e.get_error_code().get_message(), e.what());
×
1304
                if (e.get_error_code().value() ==
×
1305
                    hpx::error::commandline_option_error)
1306
                {
1307
                    std::cerr << "runtime_support::load_components: "
×
1308
                              << "invalid command line option(s) to "
×
1309
                              << instance << " component: " << e.what()
×
1310
                              << std::endl;
×
1311
                }
×
1312
            }
×
1313
        }    // for
18,545✔
1314

1315
        return 0;
593✔
1316
    }
593✔
1317

1318
    ///////////////////////////////////////////////////////////////////////////
1319
    bool runtime_support::load_startup_shutdown_functions_static(
844✔
1320
        std::string const& mod, error_code& ec)
1321
    {
1322
        try
1323
        {
1324
            // get the factory, may fail
1325
            util::plugin::get_plugins_list_type f;
1326
            if (!components::get_static_startup_shutdown(mod, f))
844✔
1327
            {
1328
                LRT_(debug).format(
754✔
1329
                    "static loading of startup/shutdown functions failed: {}: "
730✔
1330
                    "couldn't find module in global static startup/shutdown "
1331
                    "functions data map",
1332
                    mod);
730✔
1333
                return false;
754✔
1334
            }
1335

1336
            util::plugin::static_plugin_factory<component_startup_shutdown_base>
1337
                pf(f);
90✔
1338

1339
            // create the startup_shutdown object
1340
            std::shared_ptr<component_startup_shutdown_base> startup_shutdown(
90✔
1341
                pf.create("startup_shutdown", ec));
90✔
1342
            if (ec)
90✔
1343
            {
1344
                LRT_(debug).format("static loading of startup/shutdown "
×
1345
                                   "functions failed: {}: {}",
1346
                    mod, get_error_what(ec));
×
1347
                return false;
×
1348
            }
1349

1350
            startup_function_type startup;
90✔
1351
            bool pre_startup = true;
90✔
1352
            if (startup_shutdown->get_startup_function(startup, pre_startup))
90✔
1353
            {
1354
                if (!startup.empty())
90✔
1355
                {
1356
                    if (pre_startup)
90✔
1357
                    {
1358
                        pre_startup_functions_.push_back(HPX_MOVE(startup));
90✔
1359
                    }
90✔
1360
                    else
1361
                    {
1362
                        startup_functions_.push_back(HPX_MOVE(startup));
×
1363
                    }
1364
                }
90✔
1365
            }
90✔
1366

1367
            shutdown_function_type shutdown;
90✔
1368
            bool pre_shutdown = false;
90✔
1369
            if (startup_shutdown->get_shutdown_function(shutdown, pre_shutdown))
90✔
1370
            {
1371
                if (!shutdown.empty())
90✔
1372
                {
1373
                    if (pre_shutdown)
90✔
1374
                    {
1375
                        pre_shutdown_functions_.push_back(HPX_MOVE(shutdown));
×
1376
                    }
×
1377
                    else
1378
                    {
1379
                        shutdown_functions_.push_back(HPX_MOVE(shutdown));
90✔
1380
                    }
1381
                }
90✔
1382
            }
90✔
1383
        }
90✔
1384
        catch (hpx::exception const&)
1385
        {
1386
            throw;
×
1387
        }
×
1388
        catch (std::logic_error const& e)
1389
        {
1390
            LRT_(debug).format(
×
1391
                "static loading of startup/shutdown functions failed: {}: {}",
×
1392
                mod, e.what());
×
1393
            return false;
×
1394
        }
×
1395
        catch (std::exception const& e)
1396
        {
1397
            LRT_(debug).format(
×
1398
                "static loading of startup/shutdown functions failed: {}: {}",
×
1399
                mod, e.what());
×
1400
            return false;
×
1401
        }
×
1402
        return true;    // startup/shutdown functions got registered
90✔
1403
    }
844✔
1404

1405
    ///////////////////////////////////////////////////////////////////////////
1406
    bool runtime_support::load_commandline_options_static(
844✔
1407
        std::string const& mod,
1408
        hpx::program_options::options_description& options, error_code& ec)
1409
    {
1410
        try
1411
        {
1412
            util::plugin::get_plugins_list_type f;
1413
            if (!components::get_static_commandline(mod, f))
844✔
1414
            {
1415
                LRT_(debug).format("static loading of command-line options "
844✔
1416
                                   "failed: {}: couldn't find module in global "
1417
                                   "static command line data map",
1418
                    mod);
812✔
1419
                return false;
844✔
1420
            }
1421

1422
            // get the factory, may fail
1423
            hpx::util::plugin::static_plugin_factory<component_commandline_base>
1424
                pf(f);
×
1425

1426
            // create the startup_shutdown object
1427
            std::shared_ptr<component_commandline_base> commandline_options(
×
1428
                pf.create("commandline_options", ec));
×
1429
            if (ec)
×
1430
            {
1431
                LRT_(debug).format(
×
1432
                    "static loading of command-line options failed: {}: {}",
×
1433
                    mod, get_error_what(ec));
×
1434
                return false;
×
1435
            }
1436

1437
            options.add(commandline_options->add_commandline_options());
×
1438
        }
×
1439
        catch (hpx::exception const&)
1440
        {
1441
            throw;
×
1442
        }
×
1443
        catch (std::logic_error const& e)
1444
        {
1445
            LRT_(debug).format(
×
1446
                "static loading of command-line options failed: {}: {}", mod,
×
1447
                e.what());
×
1448
            return false;
×
1449
        }
×
1450
        catch (std::exception const& e)
1451
        {
1452
            LRT_(debug).format(
×
1453
                "static loading of command-line options failed: {}: {}", mod,
×
1454
                e.what());
×
1455
            return false;
×
1456
        }
×
1457
        return true;    // startup/shutdown functions got registered
×
1458
    }
844✔
1459

1460
#if !defined(HPX_HAVE_STATIC_LINKING)
1461
    bool runtime_support::load_component_dynamic(util::section& ini,
2,336✔
1462
        std::string const& instance, std::string const& component,
1463
        filesystem::path lib, naming::gid_type const& prefix,
1464
        naming::resolver_client& agas_client, bool isdefault, bool isenabled,
1465
        hpx::program_options::options_description& options,
1466
        std::set<std::string>& startup_handled)
1467
    {
1468
        modules_map_type::iterator it =
1469
            modules_.find(HPX_MANGLE_STRING(component));
2,336✔
1470
        if (it != modules_.cend())
2,336✔
1471
        {
1472
            // use loaded module, instantiate the requested factory
1473
            return load_component((*it).second, ini, instance, component, lib,
3,486✔
1474
                prefix, agas_client, isdefault, isenabled, options,
1,743✔
1475
                startup_handled);
1,743✔
1476
        }
1477

1478
        // first, try using the path as the full path to the library
1479
        error_code ec(throwmode::lightweight);
593✔
1480
        hpx::util::plugin::dll d(lib.string(), HPX_MANGLE_STRING(component));
593✔
1481
        d.load_library(ec);
593✔
1482
        if (ec)
593✔
1483
        {
1484
            // build path to component to load
1485
            std::string libname(HPX_MAKE_DLL_STRING(component));
×
1486
            lib /= filesystem::path(libname);
×
1487
            d.load_library(ec);
×
1488
            if (ec)
×
1489
            {
1490
                LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1491
                    lib.string(), instance, get_error_what(ec));
×
1492
                return false;    // next please :-P
×
1493
            }
1494
        }
×
1495

1496
        // now, instantiate the requested factory
1497
        if (!load_component(d, ini, instance, component, lib, prefix,
1,186✔
1498
                agas_client, isdefault, isenabled, options, startup_handled))
593✔
1499
        {
1500
            return false;    // next please :-P
×
1501
        }
1502

1503
        modules_.insert(std::make_pair(HPX_MANGLE_STRING(component), d));
593✔
1504
        return true;
593✔
1505
    }
2,336✔
1506

1507
    bool runtime_support::load_startup_shutdown_functions(
2,917✔
1508
        hpx::util::plugin::dll& d, error_code& ec)
1509
    {
1510
        try
1511
        {
1512
            // get the factory, may fail
1513
            hpx::util::plugin::plugin_factory<component_startup_shutdown_base>
1514
                pf(d, "startup_shutdown");
2,917✔
1515

1516
            // create the startup_shutdown object
1517
            std::shared_ptr<component_startup_shutdown_base> startup_shutdown(
2,917✔
1518
                pf.create("startup_shutdown", ec));
2,917✔
1519
            if (ec)
2,917✔
1520
            {
1521
                LRT_(debug).format(
1,171✔
1522
                    "loading of startup/shutdown functions failed: {}: {}",
578✔
1523
                    d.get_name(), get_error_what(ec));
578✔
1524
                return false;
593✔
1525
            }
1526

1527
            startup_function_type startup;
2,324✔
1528
            bool pre_startup = true;
2,324✔
1529
            if (startup_shutdown->get_startup_function(startup, pre_startup))
2,324✔
1530
            {
1531
                if (pre_startup)
1,743✔
1532
                    pre_startup_functions_.push_back(HPX_MOVE(startup));
1,743✔
1533
                else
1534
                    startup_functions_.push_back(HPX_MOVE(startup));
×
1535
            }
1,743✔
1536

1537
            shutdown_function_type shutdown;
2,324✔
1538
            bool pre_shutdown = false;
2,324✔
1539
            if (startup_shutdown->get_shutdown_function(shutdown, pre_shutdown))
2,324✔
1540
            {
1541
                if (pre_shutdown)
×
1542
                    pre_shutdown_functions_.push_back(HPX_MOVE(shutdown));
×
1543
                else
1544
                    shutdown_functions_.push_back(HPX_MOVE(shutdown));
×
1545
            }
×
1546
        }
2,917✔
1547
        catch (hpx::exception const&)
1548
        {
1549
            throw;
×
1550
        }
×
1551
        catch (std::logic_error const& e)
1552
        {
1553
            LRT_(debug).format(
×
1554
                "loading of startup/shutdown functions failed: {}: {}",
×
1555
                d.get_name(), e.what());
×
1556
            return false;
×
1557
        }
×
1558
        catch (std::exception const& e)
1559
        {
1560
            LRT_(debug).format(
×
1561
                "loading of startup/shutdown functions failed: {}: {}",
×
1562
                d.get_name(), e.what());
×
1563
            return false;
×
1564
        }
×
1565
        return true;    // startup/shutdown functions got registered
2,324✔
1566
    }
2,917✔
1567

1568
    bool runtime_support::load_commandline_options(hpx::util::plugin::dll& d,
2,917✔
1569
        hpx::program_options::options_description& options, error_code& ec)
1570
    {
1571
        try
1572
        {
1573
            // get the factory, may fail
1574
            hpx::util::plugin::plugin_factory<component_commandline_base> pf(
2,917✔
1575
                d, "commandline_options");
2,917✔
1576

1577
            // create the startup_shutdown object
1578
            std::shared_ptr<component_commandline_base> commandline_options(
2,917✔
1579
                pf.create("commandline_options", ec));
2,917✔
1580
            if (ec)
2,917✔
1581
            {
1582
                LRT_(debug).format(
4,648✔
1583
                    "loading of command-line options failed: {}: {}",
2,312✔
1584
                    d.get_name(), get_error_what(ec));
2,312✔
1585
                return false;
2,336✔
1586
            }
1587

1588
            options.add(commandline_options->add_commandline_options());
581✔
1589
        }
2,917✔
1590
        catch (hpx::exception const&)
1591
        {
1592
            throw;
×
1593
        }
×
1594
        catch (std::logic_error const& e)
1595
        {
1596
            LRT_(debug).format("loading of command-line options failed: {}: {}",
×
1597
                d.get_name(), e.what());
×
1598
            return false;
×
1599
        }
×
1600
        catch (std::exception const& e)
1601
        {
1602
            LRT_(debug).format("loading of command-line options failed: {}: {}",
×
1603
                d.get_name(), e.what());
×
1604
            return false;
×
1605
        }
×
1606
        return true;    // startup/shutdown functions got registered
581✔
1607
    }
2,917✔
1608

1609
    ///////////////////////////////////////////////////////////////////////////
1610
    bool runtime_support::load_component(hpx::util::plugin::dll& d,
2,336✔
1611
        util::section& ini, std::string const& instance,
1612
        std::string const& /* component */, filesystem::path const& lib,
1613
        naming::gid_type const& /* prefix */,
1614
        naming::resolver_client& /* agas_client */, bool /* isdefault */,
1615
        bool /* isenabled */,
1616
        hpx::program_options::options_description& options,
1617
        std::set<std::string>& startup_handled)
1618
    {
1619
#if defined(HPX_COMPUTE_DEVICE_CODE)
1620
        HPX_UNUSED(d);
1621
        HPX_UNUSED(ini);
1622
        HPX_UNUSED(instance);
1623
        HPX_UNUSED(lib);
1624
        HPX_UNUSED(options);
1625
        HPX_UNUSED(startup_handled);
1626

1627
        return false;
1628
#else
1629
        try
1630
        {
1631
            // initialize the factory instance using the preferences from the
1632
            // ini files
1633
            util::section const* component_ini = nullptr;
2,336✔
1634
            std::string component_section("hpx.components." + instance);
2,336✔
1635
            if (ini.has_section(component_section))
2,336✔
1636
                component_ini = ini.get_section(component_section);
2,336✔
1637

1638
            if (nullptr == component_ini ||
4,672✔
1639
                "0" == component_ini->get_entry("no_factory", "0"))
2,336✔
1640
            {
1641
                // get the factory
1642
                hpx::util::plugin::plugin_factory<component_factory_base> pf(
1,174✔
1643
                    d, "factory");
1,174✔
1644

1645
                LRT_(info).format("dynamic loading succeeded: {}: {}",
1,174✔
1646
                    lib.string(), instance);
1,156✔
1647
            }
1,174✔
1648

1649
            // make sure startup/shutdown registration is called once for each
1650
            // module, same for plugins
1651
            if (startup_handled.find(d.get_name()) == startup_handled.end())
2,336✔
1652
            {
1653
                error_code ec(throwmode::lightweight);
2,336✔
1654
                startup_handled.insert(d.get_name());
2,336✔
1655
                load_commandline_options(d, options, ec);
2,336✔
1656
                if (ec)
2,336✔
1657
                    ec = error_code(throwmode::lightweight);
1,755✔
1658
                load_startup_shutdown_functions(d, ec);
2,336✔
1659
            }
2,336✔
1660
        }
2,336✔
1661
        catch (hpx::exception const&)
1662
        {
1663
            throw;
×
1664
        }
×
1665
        catch (std::logic_error const& e)
1666
        {
1667
            LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1668
                lib.string(), instance, e.what());
×
1669
            return false;
×
1670
        }
×
1671
        catch (std::exception const& e)
1672
        {
1673
            LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1674
                lib.string(), instance, e.what());
×
1675
            return false;
×
1676
        }
×
1677
        return true;    // component got loaded
2,336✔
1678
#endif
1679
    }
2,336✔
1680
#endif
1681

1682
    ///////////////////////////////////////////////////////////////////////////
1683
    // Load all components from the ini files found in the configuration
1684
    bool runtime_support::load_plugins(util::section& ini,
593✔
1685
        hpx::program_options::options_description& options,
1686
        std::set<std::string>& startup_handled)
1687
    {
1688
        // load all components as described in the configuration information
1689
        if (!ini.has_section("hpx.plugins"))
593✔
1690
        {
1691
            LRT_(info).format("No plugins found/loaded.");
12✔
1692
            return true;    // no plugins to load
12✔
1693
        }
1694

1695
        // each shared library containing components may have an ini section
1696
        //
1697
        // # mandatory section describing the component module
1698
        // [hpx.plugins.instance_name]
1699
        //  name = ...           # the name of this component module
1700
        //  path = ...           # the path where to find this component module
1701
        //  enabled = false      # optional (default is assumed to be true)
1702
        //  static = false       # optional (default is assumed to be false)
1703
        //
1704
        // # optional section defining additional properties for this module
1705
        // [hpx.plugins.instance_name.settings]
1706
        //  key = value
1707
        //
1708
        util::section* sec = ini.get_section("hpx.plugins");
581✔
1709
        if (nullptr == sec)
581✔
1710
        {
1711
            LRT_(error).format("nullptr section found");
×
1712
            return false;    // something bad happened
×
1713
        }
1714

1715
        util::section::section_map const& s = (*sec).get_sections();
581✔
1716
        typedef util::section::section_map::const_iterator iterator;
1717
        iterator end = s.end();
581✔
1718
        for (iterator i = s.begin(); i != end; ++i)
1,162✔
1719
        {
1720
            namespace fs = filesystem;
1721

1722
            // the section name is the instance name of the component
1723
            util::section const& sect = i->second;
581✔
1724
            std::string instance(sect.get_name());
581✔
1725
            std::string component;
581✔
1726

1727
            if (i->second.has_entry("name"))
581✔
1728
                component = sect.get_entry("name");
581✔
1729
            else
1730
                component = instance;
×
1731

1732
            bool isenabled = true;
581✔
1733
            if (sect.has_entry("enabled"))
581✔
1734
            {
1735
                std::string tmp = sect.get_entry("enabled");
581✔
1736
                hpx::string_util::to_lower(tmp);
581✔
1737
                if (tmp == "no" || tmp == "false" || tmp == "0")
581✔
1738
                {
1739
                    LRT_(info).format("plugin factory disabled: {}", instance);
×
1740
                    isenabled = false;    // this component has been disabled
×
1741
                }
×
1742
            }
581✔
1743

1744
            fs::path lib;
581✔
1745
            try
1746
            {
1747
                std::string component_path;
581✔
1748
                if (sect.has_entry("path"))
581✔
1749
                    component_path = sect.get_entry("path");
581✔
1750
                else
1751
                    component_path = HPX_DEFAULT_COMPONENT_PATH;
×
1752

1753
                hpx::string_util::char_separator sep(HPX_INI_PATH_DELIMITER);
581✔
1754
                hpx::string_util::tokenizer tokens(component_path, sep);
581✔
1755
                std::error_code fsec;
581✔
1756
                for (auto it = tokens.begin(); it != tokens.end(); ++it)
1,127✔
1757
                {
1758
                    lib = fs::path(*it);
546✔
1759
                    fs::path lib_path =
1760
                        lib / std::string(HPX_MAKE_DLL_STRING(component));
546✔
1761
                    if (fs::exists(lib_path, fsec))
546✔
1762
                    {
1763
                        break;
273✔
1764
                    }
1765
                    lib.clear();
273✔
1766
                }
546✔
1767

1768
                if (sect.get_entry("static", "0") == "1")
581✔
1769
                {
1770
                    // FIXME: implement statically linked plugins
1771
                    HPX_THROW_EXCEPTION(hpx::error::service_unavailable,
×
1772
                        "runtime_support::load_plugins",
1773
                        "static linking configuration does not support static "
1774
                        "loading of plugin '{}'",
1775
                        instance);
1776
                }
1777
                else
1778
                {
1779
#if defined(HPX_HAVE_STATIC_LINKING)
1780
                    HPX_THROW_EXCEPTION(hpx::error::service_unavailable,
1781
                        "runtime_support::load_plugins",
1782
                        "static linking configuration does not support dynamic "
1783
                        "loading of plugin '{}'",
1784
                        instance);
1785
#else
1786
                    // first, try using the path as the full path to the library
1787
                    load_plugin_dynamic(ini, instance, component, lib,
581✔
1788
                        isenabled, options, startup_handled);
581✔
1789
#endif
1790
                }
1791
            }
581✔
1792
            catch (hpx::exception const& e)
1793
            {
1794
                LRT_(warning).format(
×
1795
                    "caught exception while loading {}, {}: {}", instance,
×
1796
                    e.get_error_code().get_message(), e.what());
×
1797
                if (e.get_error_code().value() ==
×
1798
                    hpx::error::commandline_option_error)
1799
                {
1800
                    std::cerr << "runtime_support::load_plugins: "
×
1801
                              << "invalid command line option(s) to "
×
1802
                              << instance << " component: " << e.what()
×
1803
                              << std::endl;
×
1804
                }
×
1805
            }
×
1806
        }    // for
581✔
1807
        return true;
581✔
1808
    }
593✔
1809

1810
#if !defined(HPX_HAVE_STATIC_LINKING)
1811
    bool runtime_support::load_plugin(hpx::util::plugin::dll& d,
581✔
1812
        util::section& ini, std::string const& instance,
1813
        std::string const& /* plugin */, filesystem::path const& lib,
1814
        bool isenabled, hpx::program_options::options_description& options,
1815
        std::set<std::string>& startup_handled)
1816
    {
1817
        try
1818
        {
1819
            // initialize the factory instance using the preferences from the
1820
            // ini files
1821
            util::section const* glob_ini = nullptr;
581✔
1822
            if (ini.has_section("settings"))
581✔
1823
                glob_ini = ini.get_section("settings");
×
1824

1825
            util::section const* plugin_ini = nullptr;
581✔
1826
            std::string plugin_section("hpx.plugins." + instance);
581✔
1827
            if (ini.has_section(plugin_section))
581✔
1828
                plugin_ini = ini.get_section(plugin_section);
581✔
1829

1830
            error_code ec(throwmode::lightweight);
581✔
1831
            if (nullptr == plugin_ini ||
1,162✔
1832
                "0" == plugin_ini->get_entry("no_factory", "0"))
581✔
1833
            {
1834
                // get the factory
1835
                hpx::util::plugin::plugin_factory<plugins::plugin_factory_base>
1836
                    pf(d, "factory");
581✔
1837

1838
                // create the component factory object, if not disabled
1839
                std::shared_ptr<plugins::plugin_factory_base> factory(
581✔
1840
                    pf.create(instance, ec, glob_ini, plugin_ini, isenabled));
581✔
1841
                if (!ec)
581✔
1842
                {
1843
                    // store component factory and module for later use
1844
                    plugin_factory_type data(factory, d, isenabled);
581✔
1845
                    std::pair<plugin_map_type::iterator, bool> p =
1846
                        plugins_.insert(
581✔
1847
                            plugin_map_type::value_type(instance, data));
581✔
1848

1849
                    if (!p.second)
581✔
1850
                    {
1851
                        LRT_(fatal).format(
×
1852
                            "duplicate plugin type: {}", instance);
×
1853
                        return false;
×
1854
                    }
1855

1856
                    LRT_(info).format("dynamic loading succeeded: {}: {}",
581✔
1857
                        lib.string(), instance);
578✔
1858
                }
581✔
1859
                else
1860
                {
1861
                    LRT_(warning).format(
×
1862
                        "dynamic loading of plugin factory failed: {}: {}: {}",
×
1863
                        lib.string(), instance, get_error_what(ec));
×
1864
                }
1865
            }
581✔
1866

1867
            // make sure startup/shutdown registration is called once for each
1868
            // module, same for plugins
1869
            if (startup_handled.find(d.get_name()) == startup_handled.end())
581✔
1870
            {
1871
                startup_handled.insert(d.get_name());
581✔
1872
                load_commandline_options(d, options, ec);
581✔
1873
                if (ec)
581✔
1874
                    ec = error_code(throwmode::lightweight);
581✔
1875
                load_startup_shutdown_functions(d, ec);
581✔
1876
            }
581✔
1877
        }
581✔
1878
        catch (hpx::exception const&)
1879
        {
1880
            throw;
×
1881
        }
×
1882
        catch (std::logic_error const& e)
1883
        {
1884
            LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1885
                lib.string(), instance, e.what());
×
1886
            return false;
×
1887
        }
×
1888
        catch (std::exception const& e)
1889
        {
1890
            LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1891
                lib.string(), instance, e.what());
×
1892
            return false;
×
1893
        }
×
1894
        return true;
581✔
1895
    }
581✔
1896

1897
    bool runtime_support::load_plugin_dynamic(util::section& ini,
581✔
1898
        std::string const& instance, std::string const& plugin,
1899
        filesystem::path lib, bool isenabled,
1900
        hpx::program_options::options_description& options,
1901
        std::set<std::string>& startup_handled)
1902
    {
1903
        modules_map_type::iterator it =
1904
            modules_.find(HPX_MANGLE_STRING(plugin));
581✔
1905
        if (it != modules_.cend())
581✔
1906
        {
1907
            // use loaded module, instantiate the requested factory
1908
            return load_plugin((*it).second, ini, instance, plugin, lib,
1,162✔
1909
                isenabled, options, startup_handled);
581✔
1910
        }
1911

1912
        // get the handle of the library
1913
        error_code ec(throwmode::lightweight);
×
1914
        hpx::util::plugin::dll d(lib.string(), HPX_MANGLE_STRING(plugin));
×
1915
        d.load_library(ec);
×
1916
        if (ec)
×
1917
        {
1918
            // build path to component to load
1919
            std::string libname(HPX_MAKE_DLL_STRING(plugin));
×
1920
            lib /= filesystem::path(libname);
×
1921
            d.load_library(ec);
×
1922
            if (ec)
×
1923
            {
1924
                LRT_(warning).format("dynamic loading failed: {}: {}: {}",
×
1925
                    lib.string(), instance, get_error_what(ec));
×
1926
                return false;    // next please :-P
×
1927
            }
1928
        }
×
1929

1930
        // now, instantiate the requested factory
1931
        if (!load_plugin(d, ini, instance, plugin, lib, isenabled, options,
×
1932
                startup_handled))
×
1933
        {
1934
            return false;    // next please :-P
×
1935
        }
1936

1937
        modules_.insert(std::make_pair(HPX_MANGLE_STRING(plugin), d));
×
1938
        return true;    // plugin got loaded
×
1939
    }
581✔
1940
#endif
1941
}}}    // namespace hpx::components::server
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