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

STEllAR-GROUP / hpx / #844

02 Dec 2022 12:37AM UTC coverage: 85.8% (+0.2%) from 85.634%
#844

push

StellarBot
Merge #6084

6084: Renaming hpx::apply and friends to hpx::post r=hkaiser a=hkaiser

- this is needed to be able to rename invoke_fused to apply later

working towards https://github.com/STEllAR-GROUP/hpx/issues/5497



Co-authored-by: Hartmut Kaiser <hartmut.kaiser@gmail.com>

468 of 468 new or added lines in 96 files covered. (100.0%)

171389 of 199753 relevant lines covered (85.8%)

1914550.97 hits per line

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

67.58
/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/threadmanager.hpp>
29
#include <hpx/modules/timing.hpp>
30
#include <hpx/performance_counters/counters.hpp>
31
#include <hpx/plugin_factories/binary_filter_factory_base.hpp>
32
#include <hpx/plugin_factories/message_handler_factory_base.hpp>
33
#include <hpx/prefix/find_prefix.hpp>
34
#include <hpx/runtime_components/console_logging.hpp>
35
#include <hpx/runtime_configuration/component_commandline_base.hpp>
36
#include <hpx/runtime_configuration/component_factory_base.hpp>
37
#include <hpx/runtime_configuration/static_factory_data.hpp>
38
#include <hpx/runtime_distributed.hpp>
39
#include <hpx/runtime_distributed/find_localities.hpp>
40
#include <hpx/runtime_distributed/runtime_fwd.hpp>
41
#include <hpx/runtime_distributed/server/runtime_support.hpp>
42
#include <hpx/runtime_distributed/stubs/runtime_support.hpp>
43
#include <hpx/runtime_local/component_startup_shutdown_base.hpp>
44
#include <hpx/runtime_local/runtime_local.hpp>
45
#include <hpx/runtime_local/shutdown_function.hpp>
46
#include <hpx/runtime_local/startup_function.hpp>
47
#include <hpx/serialization/serialize.hpp>
48
#include <hpx/serialization/vector.hpp>
49
#include <hpx/string_util/case_conv.hpp>
50
#include <hpx/thread_support/unlock_guard.hpp>
51
#include <hpx/type_support/unused.hpp>
52
#include <hpx/util/from_string.hpp>
53

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

58
#include <boost/tokenizer.hpp>
59

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

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

122
///////////////////////////////////////////////////////////////////////////////
123
HPX_DEFINE_COMPONENT_NAME(
×
124
    hpx::components::server::runtime_support, hpx_runtime_support)
125
HPX_DEFINE_GET_COMPONENT_TYPE_STATIC(hpx::components::server::runtime_support,
14,644✔
126
    hpx::components::component_runtime_support)
127

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

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

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

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

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

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

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

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

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

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

246
        tm.wait();
1,124✔
247
        tm.cleanup_terminated(true);
1,124✔
248

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

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

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

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

286
        agas_client.start_shutdown();
1,124✔
287

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

291
        std::uint32_t locality_id = get_locality_id();
1,124✔
292

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

302
            dijkstra_cond_.notify_one();
560✔
303
            return;
560✔
304
        }
305

306
        if (0 == locality_id)
564✔
307
            locality_id = num_localities;
×
308

309
        send_dijkstra_termination_token(locality_id - 1, initiating_locality_id,
1,128✔
310
            num_localities, dijkstra_token);
564✔
311
    }
1,124✔
312
#endif
313

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

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

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

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

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

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

346
        std::size_t count = 0;    // keep track of number of trials
280✔
347

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

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

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

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

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

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

382
                ++count;
560✔
383

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

392
            } while (dijkstra_color_);
560✔
393
        }
280✔
394

395
        return count;
280✔
396
#endif
397
    }
904✔
398

399
    ///////////////////////////////////////////////////////////////////////////
400
    void runtime_support::shutdown_all(double timeout)
479✔
401
    {
402
        if (find_here() != hpx::find_root_locality())
479✔
403
        {
404
            HPX_THROW_EXCEPTION(invalid_status, "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;
479✔
411
        if (!shutdown_all_invoked_.compare_exchange_strong(flag, true))
479✔
412
        {
413
            return;
27✔
414
        }
415

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

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

422
        agas_client.start_shutdown();
452✔
423

424
        stop_evaluating_counters(true);
452✔
425

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

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

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

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

441
        LRT_(info).format(
452✔
442
            "runtime_support::shutdown_all: invoked shutdown functions");
438✔
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);
452✔
448

449
        LRT_(info).format("runtime_support::shutdown_all: passed second "
452✔
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());
452✔
457
        std::uint32_t locality_id = get_locality_id();
452✔
458
        std::vector<hpx::future<void>> lazy_actions;
452✔
459

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

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

473
        LRT_(info).format("runtime_support::shutdown_all: all localities have "
452✔
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);
452✔
479
    }
479✔
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()
593✔
540
    {
541
        pre_startup_functions_.clear();
593✔
542
        startup_functions_.clear();
593✔
543
        pre_shutdown_functions_.clear();
593✔
544
        shutdown_functions_.clear();
593✔
545
    }
593✔
546

547
    void runtime_support::tidy()
1,186✔
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,186✔
552
        modules_.clear();    // unload all modules
1,186✔
553
    }
1,186✔
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()
594✔
575
    {
576
        std::unique_lock<std::mutex> l(mtx_);
594✔
577
        stop_called_ = false;
594✔
578
        stop_done_ = false;
594✔
579
        terminated_ = false;
594✔
580
        shutdown_all_invoked_.store(false);
594✔
581
    }
594✔
582

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

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

603
            HPX_ASSERT(!terminated_);
594✔
604

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

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

611
            stop_called_ = true;
594✔
612

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

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

629
                // If it took longer than expected, kill all suspended threads as
630
                // well.
631
                if (!success)
594✔
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();
594✔
648

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

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

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

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

661
                if (respond_to)
594✔
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;
141✔
674
                    if (agas::is_local_address_cached(respond_to, addr))
141✔
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>(
141✔
685
                            HPX_MOVE(addr), respond_to);
141✔
686
#else
687
                        HPX_ASSERT(false);
688
#endif
689
                    }
690
#endif
691
                }
141✔
692
            }
594✔
693

694
            stop_done_ = true;
594✔
695
            wait_condition_.notify_all();
594✔
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_)
594✔
700
            {
701
                stop_condition_.wait(l);    // wait for termination
594✔
702
            }
594✔
703
        }
594✔
704
    }
594✔
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()
594✔
726
    {
727
        std::lock_guard<std::mutex> l(mtx_);
594✔
728
        if (!terminated_)
594✔
729
        {
730
            terminated_ = true;
594✔
731
            stop_condition_.notify_all();    // finished cleanup/termination
594✔
732
        }
594✔
733
    }
594✔
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()
594✔
754
    {
755
        // load components now that AGAS is up
756
        util::runtime_configuration& ini = get_runtime().get_config();
594✔
757

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

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

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

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

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

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

785
#if defined(HPX_HAVE_NETWORKING)
786
        return util::handle_late_commandline_options(ini, options,
594✔
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
    }
594✔
793

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

814
    void runtime_support::call_shutdown_functions(bool pre_shutdown)
1,188✔
815
    {
816
        runtime& rt = get_runtime();
1,188✔
817
        if (pre_shutdown)
1,188✔
818
        {
819
            rt.set_state(hpx::state::pre_shutdown);
594✔
820
            for (shutdown_function_type& f : pre_shutdown_functions_)
1,192✔
821
            {
822
                try
823
                {
824
                    f();
598✔
825
                }
598✔
826
                catch (...)
827
                {
828
                    rt.report_error(std::current_exception());
×
829
                }
×
830
            }
831
        }
594✔
832
        else
833
        {
834
            rt.set_state(hpx::state::shutdown);
594✔
835
            for (shutdown_function_type& f : shutdown_functions_)
73,986✔
836
            {
837
                try
838
                {
839
                    f();
73,392✔
840
                }
73,392✔
841
                catch (...)
842
                {
843
                    rt.report_error(std::current_exception());
×
844
                }
×
845
            }
846
        }
847
    }
1,188✔
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,205✔
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,205✔
946

947
        plugin_map_type::const_iterator it =
948
            plugins_.find(message_handler_type);
20,205✔
949
        if (it == plugins_.end() || !(*it).second.first)
20,205✔
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::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::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,797✔
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,797✔
977
                (*it).second.first));
19,797✔
978

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

981
        if (ec)
19,797✔
982
        {
983
            HPX_THROWS_IF(ec, hpx::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,797✔
992
            ec = make_success_code();
19,797✔
993

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

1000
    parcelset::policies::message_handler*
1001
    runtime_support::create_message_handler(char const* message_handler_type,
286✔
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_);
286✔
1008

1009
        plugin_map_type::const_iterator it =
1010
            plugins_.find(message_handler_type);
286✔
1011
        if (it == plugins_.end() || !(*it).second.first)
286✔
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::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::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();
286✔
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>(
286✔
1039
                (*it).second.first));
286✔
1040

1041
        parcelset::policies::message_handler* mh =
286✔
1042
            factory->create(action, pp, num_messages, interval);
286✔
1043
        if (nullptr == mh)
286✔
1044
        {
1045
            HPX_THROWS_IF(ec, hpx::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)
286✔
1053
            ec = make_success_code();
284✔
1054

1055
        // log result if requested
1056
        LRT_(info).format(
286✔
1057
            "successfully created message handler plugin of type: {}",
285✔
1058
            message_handler_type);
1059
        return mh;
286✔
1060
    }
286✔
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::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::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,237✔
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,237✔
1126
            std::string component_section("hpx.components." + instance);
16,237✔
1127
            if (ini.has_section(component_section))
16,237✔
1128
                component_ini = ini.get_section(component_section);
16,237✔
1129

1130
            if (nullptr == component_ini ||
32,474✔
1131
                "0" == component_ini->get_entry("no_factory", "0"))
16,237✔
1132
            {
1133
                util::plugin::get_plugins_list_type f;
1134
                if (!components::get_static_factory(instance, f))
16,237✔
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,237✔
1144
                    "static loading succeeded: {}: {}", lib.string(), instance);
15,830✔
1145
            }
16,237✔
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,237✔
1150
            {
1151
                error_code ec(throwmode::lightweight);
846✔
1152
                startup_handled.insert(component);
846✔
1153
                load_commandline_options_static(component, options, ec);
846✔
1154
                if (ec)
846✔
1155
                    ec = error_code(throwmode::lightweight);
×
1156
                load_startup_shutdown_functions_static(component, ec);
846✔
1157
            }
846✔
1158
        }
16,237✔
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,237✔
1176
    }
16,237✔
1177

1178
    ///////////////////////////////////////////////////////////////////////////
1179
    // Load all components from the ini files found in the configuration
1180
    int runtime_support::load_components(util::section& ini,
594✔
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"))
594✔
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");
594✔
1208
        if (nullptr == sec)
594✔
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();
594✔
1215
        typedef util::section::section_map::const_iterator iterator;
1216
        iterator end = s.end();
594✔
1217
        for (iterator i = s.begin(); i != end; ++i)
19,171✔
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,577✔
1223
            std::string instance(sect.get_name());
18,577✔
1224
            std::string component;
18,577✔
1225

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

1231
            bool isenabled = true;
18,577✔
1232
            if (sect.has_entry("enabled"))
18,577✔
1233
            {
1234
                std::string tmp = sect.get_entry("enabled");
18,577✔
1235
                hpx::string_util::to_lower(tmp);
18,577✔
1236
                if (tmp == "no" || tmp == "false" || tmp == "0")
18,577✔
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,577✔
1243

1244
            // test whether this component section was generated
1245
            bool isdefault = false;
18,577✔
1246
            if (sect.has_entry("isdefault"))
18,577✔
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,577✔
1255
            try
1256
            {
1257
                std::string component_path;
18,577✔
1258
                if (sect.has_entry("path"))
18,577✔
1259
                    component_path = sect.get_entry("path");
4,716✔
1260
                else
1261
                    component_path = HPX_DEFAULT_COMPONENT_PATH;
13,861✔
1262

1263
                typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
1264
                boost::char_separator<char> sep(HPX_INI_PATH_DELIMITER);
18,577✔
1265
                tokenizer tokens(component_path, sep);
18,577✔
1266
                std::error_code fsec;
18,577✔
1267
                for (tokenizer::iterator it = tokens.begin();
69,432✔
1268
                     it != tokens.end(); ++it)
49,109✔
1269
                {
1270
                    lib = fs::path(*it);
17,012✔
1271
                    fs::path lib_path =
1272
                        lib / std::string(HPX_MAKE_DLL_STRING(component));
17,012✔
1273
                    if (fs::exists(lib_path, fsec))
17,012✔
1274
                    {
1275
                        break;
1,746✔
1276
                    }
1277
                    lib.clear();
15,266✔
1278
                }
17,012✔
1279

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

1316
        return 0;
594✔
1317
    }
594✔
1318

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

1337
            util::plugin::static_plugin_factory<component_startup_shutdown_base>
1338
                pf(f);
91✔
1339

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

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

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

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

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

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

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

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

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

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

1504
        modules_.insert(std::make_pair(HPX_MANGLE_STRING(component), d));
594✔
1505
        return true;
594✔
1506
    }
2,340✔
1507

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

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

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

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

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

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

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

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

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

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

1646
                LRT_(info).format("dynamic loading succeeded: {}: {}",
1,176✔
1647
                    lib.string(), instance);
1,158✔
1648
            }
1,176✔
1649

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

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

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

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

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

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

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

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

1754
                typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
1755
                boost::char_separator<char> sep(HPX_INI_PATH_DELIMITER);
582✔
1756
                tokenizer tokens(component_path, sep);
582✔
1757
                std::error_code fsec;
582✔
1758
                for (tokenizer::iterator it = tokens.begin();
1,983✔
1759
                     it != tokens.end(); ++it)
1,128✔
1760
                {
1761
                    lib = fs::path(*it);
546✔
1762
                    fs::path lib_path =
1763
                        lib / std::string(HPX_MAKE_DLL_STRING(component));
546✔
1764
                    if (fs::exists(lib_path, fsec))
546✔
1765
                    {
1766
                        break;
273✔
1767
                    }
1768
                    lib.clear();
273✔
1769
                }
546✔
1770

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

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

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

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

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

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

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

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

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

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

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

1939
        modules_.insert(std::make_pair(HPX_MANGLE_STRING(plugin), d));
×
1940
        return true;    // plugin got loaded
×
1941
    }
582✔
1942
#endif
1943
}}}    // 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