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

STEllAR-GROUP / hpx / #862

10 Jan 2023 05:30PM UTC coverage: 86.582% (-0.05%) from 86.634%
#862

push

StellarBot
Merge #6130

6130: Remove the mutex lock in the critical path of get_partitioner. r=hkaiser a=JiakunYan

Remove the mutex lock in the critical path of hpx::resource::detail::get_partitioner.

The protected variable `partitioner_ref` is only set once during initialization.

Co-authored-by: Jiakun Yan <jiakunyan1998@gmail.com>

6 of 6 new or added lines in 1 file covered. (100.0%)

174767 of 201851 relevant lines covered (86.58%)

2069816.07 hits per line

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

74.14
/libs/core/runtime_configuration/src/init_ini_data.cpp
1
//  Copyright (c) 2005-2017 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#include <hpx/assert.hpp>
10
#include <hpx/ini/ini.hpp>
11
#include <hpx/modules/errors.hpp>
12
#include <hpx/modules/filesystem.hpp>
13
#include <hpx/modules/logging.hpp>
14
#include <hpx/modules/plugin.hpp>
15
#include <hpx/modules/string_util.hpp>
16
#include <hpx/prefix/find_prefix.hpp>
17
#include <hpx/runtime_configuration/component_registry_base.hpp>
18
#include <hpx/runtime_configuration/init_ini_data.hpp>
19
#include <hpx/runtime_configuration/plugin_registry_base.hpp>
20
#include <hpx/version.hpp>
21

22
#include <algorithm>
23
#include <iostream>
24
#include <map>
25
#include <memory>
26
#include <random>
27
#include <string>
28
#include <system_error>
29
#include <utility>
30
#include <vector>
31

32
///////////////////////////////////////////////////////////////////////////////
33
namespace hpx { namespace util {
34
    ///////////////////////////////////////////////////////////////////////////
35
    bool handle_ini_file(section& ini, std::string const& loc)
42,820✔
36
    {
37
        try
38
        {
39
            namespace fs = filesystem;
40
            std::error_code ec;
42,820✔
41
            if (!fs::exists(loc, ec) || ec)
42,820✔
42
                return false;    // avoid exception on missing file
42,820✔
43
            ini.read(loc);
×
44
        }
×
45
        catch (hpx::exception const& /*e*/)
46
        {
47
            return false;
×
48
        }
×
49
        return true;
×
50
    }
42,820✔
51

52
    ///////////////////////////////////////////////////////////////////////////
53
    bool handle_ini_file_env(
18,159✔
54
        section& ini, char const* env_var, char const* file_suffix)
55
    {
56
        char const* env = getenv(env_var);
18,159✔
57
        if (nullptr != env)
18,159✔
58
        {
59
            namespace fs = filesystem;
60

61
            fs::path inipath(env);
12,106✔
62
            if (nullptr != file_suffix)
12,106✔
63
                inipath /= fs::path(file_suffix);
12,106✔
64

65
            if (handle_ini_file(ini, inipath.string()))
12,106✔
66
            {
67
                LBT_(info).format("loaded configuration (${{{}}}): {}", env_var,
×
68
                    inipath.string());
×
69
                return true;
×
70
            }
71
        }
12,106✔
72
        return false;
18,159✔
73
    }
18,159✔
74

75
    ///////////////////////////////////////////////////////////////////////////
76
    // read system and user specified ini files
77
    //
78
    // returns true if at least one alternative location has been read
79
    // successfully
80
    bool init_ini_data_base(section& ini, std::string& hpx_ini_file)
6,053✔
81
    {
82
        namespace fs = filesystem;
83

84
        // fall back: use compile time prefix
85
        std::string ini_paths(ini.get_entry("hpx.master_ini_path"));
6,053✔
86
        std::string ini_paths_suffixes(
87
            ini.get_entry("hpx.master_ini_path_suffixes"));
6,053✔
88

89
        // split off the separate paths from the given path list
90
        hpx::string_util::char_separator sep(HPX_INI_PATH_DELIMITER);
6,053✔
91
        hpx::string_util::tokenizer tok_paths(ini_paths, sep);
6,053✔
92
        auto end_paths = tok_paths.end();
6,053✔
93
        hpx::string_util::tokenizer tok_suffixes(ini_paths_suffixes, sep);
6,053✔
94
        auto end_suffixes = tok_suffixes.end();
6,053✔
95

96
        bool result = false;
6,053✔
97
        for (auto it = tok_paths.begin(); it != end_paths; ++it)
15,357✔
98
        {
99
            for (auto jt = tok_suffixes.begin(); jt != end_suffixes; ++jt)
27,912✔
100
            {
101
                std::string path = *it;
18,608✔
102
                path += *jt;
18,608✔
103
                bool result2 = handle_ini_file(ini, path + "/hpx.ini");
18,608✔
104
                if (result2)
18,608✔
105
                {
106
                    LBT_(info).format("loaded configuration: {}/hpx.ini", path);
×
107
                }
×
108
                result = result2 || result;
18,608✔
109
            }
18,608✔
110
        }
9,304✔
111

112
        // look in the current directory first
113
        std::string cwd = fs::current_path().string() + "/.hpx.ini";
6,053✔
114
        {
115
            bool result2 = handle_ini_file(ini, cwd);
6,053✔
116
            if (result2)
6,053✔
117
            {
118
                LBT_(info).format("loaded configuration: {}", cwd);
×
119
            }
×
120
            result = result2 || result;
6,053✔
121
        }
122

123
        // look for master ini in the HPX_INI environment
124
        result = handle_ini_file_env(ini, "HPX_INI") || result;
6,053✔
125

126
        // afterwards in the standard locations
127
#if !defined(HPX_WINDOWS)    // /etc/hpx.ini doesn't make sense for Windows
128
        {
129
            bool result2 = handle_ini_file(ini, "/etc/hpx.ini");
6,053✔
130
            if (result2)
6,053✔
131
            {
132
                LBT_(info).format("loaded configuration: /etc/hpx.ini");
×
133
            }
×
134
            result = result2 || result;
6,053✔
135
        }
136
#endif
137

138
        result = handle_ini_file_env(ini, "HOME", ".hpx.ini") || result;
6,053✔
139
        result = handle_ini_file_env(ini, "PWD", ".hpx.ini") || result;
6,053✔
140

141
        if (!hpx_ini_file.empty())
6,053✔
142
        {
143
            namespace fs = filesystem;
144
            std::error_code ec;
×
145
            if (!fs::exists(hpx_ini_file, ec) || ec)
×
146
            {
147
                std::cerr
148
                    << "hpx::init: command line warning: file specified using "
×
149
                       "--hpx:config does not exist ("
150
                    << hpx_ini_file << ")." << std::endl;
×
151
                hpx_ini_file.clear();
×
152
                result = false;
×
153
            }
×
154
            else
155
            {
156
                bool result2 = handle_ini_file(ini, hpx_ini_file);
×
157
                if (result2)
×
158
                {
159
                    LBT_(info).format("loaded configuration: {}", hpx_ini_file);
×
160
                }
×
161
                return result || result2;
×
162
            }
163
        }
×
164
        return result;
6,053✔
165
    }
6,053✔
166

167
    ///////////////////////////////////////////////////////////////////////////
168
    // global function to read component ini information
169
    void merge_component_inis(section& ini)
1,192✔
170
    {
171
        namespace fs = filesystem;
172

173
        // now merge all information into one global structure
174
        std::string ini_path(
175
            ini.get_entry("hpx.ini_path", HPX_DEFAULT_INI_PATH));
1,192✔
176
        std::vector<std::string> ini_paths;
1,192✔
177

178
        // split off the separate paths from the given path list
179
        hpx::string_util::char_separator sep(HPX_INI_PATH_DELIMITER);
1,192✔
180
        hpx::string_util::tokenizer tok(ini_path, sep);
1,192✔
181
        auto end = tok.end();
1,192✔
182
        for (auto it = tok.begin(); it != end; ++it)
2,292✔
183
            ini_paths.push_back(*it);
1,100✔
184

185
        // have all path elements, now find ini files in there...
186
        std::vector<std::string>::iterator ini_end = ini_paths.end();
1,192✔
187
        for (std::vector<std::string>::iterator it = ini_paths.begin();
2,292✔
188
             it != ini_end; ++it)
2,292✔
189
        {
190
            try
191
            {
192
                fs::directory_iterator nodir;
1,100✔
193
                fs::path this_path(*it);
1,100✔
194

195
                std::error_code ec;
1,100✔
196
                if (!fs::exists(this_path, ec) || ec)
1,100✔
197
                    continue;
1,100✔
198

199
                for (fs::directory_iterator dir(this_path); dir != nodir; ++dir)
×
200
                {
201
                    auto& p = dir->path();
×
202
                    if (p.extension() != ".ini")
×
203
                        continue;
×
204

205
                    // read and merge the ini file into the main ini hierarchy
206
                    try
207
                    {
208
                        ini.merge(p.string());
×
209
                        LBT_(info).format(
×
210
                            "loaded configuration: {}", p.string());
×
211
                    }
×
212
                    catch (hpx::exception const& /*e*/)
213
                    {
214
                        ;
215
                    }
×
216
                }
×
217
            }
1,100✔
218
            catch (fs::filesystem_error const& /*e*/)
219
            {
220
                ;
221
            }
×
222
        }
×
223
    }
1,192✔
224

225
    ///////////////////////////////////////////////////////////////////////////
226
    // iterate over all shared libraries in the given directory and construct
227
    // default ini settings assuming all of those are components
228
    std::vector<std::shared_ptr<components::component_registry_base>>
229
    load_component_factory_static(util::section& ini, std::string name,
847✔
230
        hpx::util::plugin::get_plugins_list_type get_factory, error_code& ec)
231
    {
232
        hpx::util::plugin::static_plugin_factory<
233
            components::component_registry_base>
234
            pf(get_factory);
847✔
235
        std::vector<std::shared_ptr<components::component_registry_base>>
847✔
236
            registries;
847✔
237

238
        // retrieve the names of all known registries
239
        std::vector<std::string> names;
847✔
240
        pf.get_names(names, ec);
847✔
241
        if (ec)
847✔
242
            return registries;
×
243

244
        std::vector<std::string> ini_data;
847✔
245
        if (names.empty())
847✔
246
        {
247
            // This HPX module does not export any factories, but
248
            // might export startup/shutdown functions. Create some
249
            // default configuration data.
250
#if defined(HPX_DEBUG)
251
            // demangle the name in debug mode
252
            if (name[name.size() - 1] == 'd')
×
253
                name.resize(name.size() - 1);
×
254
#endif
255
            ini_data.emplace_back("[hpx.components." + name + "]");
×
256
            ini_data.emplace_back("name = " + name);
×
257
            ini_data.emplace_back("no_factory = 1");
×
258
            ini_data.emplace_back("enabled = 1");
×
259
            ini_data.emplace_back("static = 1");
×
260
        }
×
261
        else
262
        {
263
            registries.reserve(names.size());
847✔
264
            // ask all registries
265
            for (std::string const& s : names)
17,138✔
266
            {
267
                // create the component registry object
268
                std::shared_ptr<components::component_registry_base> registry(
16,291✔
269
                    pf.create(s, ec));
16,291✔
270
                if (ec)
16,291✔
271
                    continue;
×
272

273
                registry->get_component_info(ini_data, "", true);
16,291✔
274
                registries.push_back(registry);
16,291✔
275
            }
16,291✔
276
        }
277

278
        // incorporate all information from this module's
279
        // registry into our internal ini object
280
        ini.parse("<component registry>", ini_data, false, false);
847✔
281
        return registries;
847✔
282
    }
847✔
283

284
    void load_component_factory(hpx::util::plugin::dll& d, util::section& ini,
2,344✔
285
        std::string const& curr,
286
        std::vector<std::shared_ptr<components::component_registry_base>>&
287
            component_registries,
288
        std::string name, error_code& ec)
289
    {
290
        hpx::util::plugin::plugin_factory<components::component_registry_base>
291
            pf(d, "registry");
2,344✔
292

293
        // retrieve the names of all known registries
294
        std::vector<std::string> names;
2,344✔
295
        pf.get_names(names, ec);
2,344✔
296
        if (ec)
2,344✔
297
            return;
586✔
298

299
        std::vector<std::string> ini_data;
1,758✔
300
        if (names.empty())
1,758✔
301
        {
302
            // This HPX module does not export any factories, but
303
            // might export startup/shutdown functions. Create some
304
            // default configuration data.
305
#if defined(HPX_DEBUG)
306
            // demangle the name in debug mode
307
            if (name[name.size() - 1] == 'd')
1,172✔
308
                name.resize(name.size() - 1);
1,172✔
309
#endif
310
            ini_data.emplace_back("[hpx.components." + name + "]");
1,172✔
311
            ini_data.emplace_back("name = " + name);
1,172✔
312
            ini_data.emplace_back("path = " + curr);
1,172✔
313
            ini_data.emplace_back("no_factory = 1");
1,172✔
314
            ini_data.emplace_back("enabled = 1");
1,172✔
315
        }
1,172✔
316
        else
317
        {
318
            // ask all registries
319
            for (std::string const& s : names)
1,172✔
320
            {
321
                // create the component registry object
322
                std::shared_ptr<components::component_registry_base> registry(
586✔
323
                    pf.create(s, ec));
586✔
324
                if (ec)
586✔
325
                    return;
×
326

327
                registry->get_component_info(ini_data, curr);
586✔
328
                component_registries.push_back(registry);
586✔
329
            }
586✔
330
        }
331

332
        // incorporate all information from this module's
333
        // registry into our internal ini object
334
        ini.parse("<component registry>", ini_data, false, false);
1,758✔
335
    }
2,344✔
336

337
    ///////////////////////////////////////////////////////////////////////////
338
    std::vector<std::shared_ptr<plugins::plugin_registry_base>>
339
    load_plugin_factory(hpx::util::plugin::dll& d, util::section& ini,
2,344✔
340
        std::string const& /* curr */, std::string const& /* name */,
341
        error_code& ec)
342
    {
343
        typedef std::vector<std::shared_ptr<plugins::plugin_registry_base>>
344
            plugin_list_type;
345

346
        plugin_list_type plugin_registries;
2,344✔
347
        hpx::util::plugin::plugin_factory<plugins::plugin_registry_base> pf(
2,344✔
348
            d, "plugin");
2,344✔
349

350
        // retrieve the names of all known registries
351
        std::vector<std::string> names;
2,344✔
352
        pf.get_names(names, ec);    // throws on error
2,344✔
353
        if (ec)
2,344✔
354
            return plugin_registries;
1,758✔
355

356
        std::vector<std::string> ini_data;
586✔
357
        if (!names.empty())
586✔
358
        {
359
            // ask all registries
360
            for (std::string const& s : names)
1,172✔
361
            {
362
                // create the plugin registry object
363
                std::shared_ptr<plugins::plugin_registry_base> registry(
586✔
364
                    pf.create(s, ec));
586✔
365
                if (ec)
586✔
366
                    continue;
×
367

368
                registry->get_plugin_info(ini_data);
586✔
369
                plugin_registries.push_back(registry);
586✔
370
            }
586✔
371
        }
586✔
372

373
        // incorporate all information from this module's
374
        // registry into our internal ini object
375
        ini.parse("<plugin registry>", ini_data, false, false);
586✔
376
        return plugin_registries;
586✔
377
    }
2,344✔
378

379
    namespace detail {
380
        inline bool cmppath_less(
381
            std::pair<filesystem::path, std::string> const& lhs,
382
            std::pair<filesystem::path, std::string> const& rhs)
383
        {
384
            return lhs.first < rhs.first;
385
        }
386

387
        inline bool cmppath_equal(
388
            std::pair<filesystem::path, std::string> const& lhs,
389
            std::pair<filesystem::path, std::string> const& rhs)
390
        {
391
            return lhs.first == rhs.first;
392
        }
393
    }    // namespace detail
394

395
    ///////////////////////////////////////////////////////////////////////////
396
    std::vector<std::shared_ptr<plugins::plugin_registry_base>>
397
    init_ini_data_default(std::string const& libs, util::section& ini,
586✔
398
        std::map<std::string, filesystem::path>& basenames,
399
        std::map<std::string, hpx::util::plugin::dll>& modules,
400
        std::vector<std::shared_ptr<components::component_registry_base>>&
401
            component_registries)
402
    {
403
        namespace fs = filesystem;
404

405
        typedef std::vector<std::shared_ptr<plugins::plugin_registry_base>>
406
            plugin_list_type;
407

408
        plugin_list_type plugin_registries;
586✔
409

410
        // list of modules to load
411
        std::vector<std::pair<fs::path, std::string>> libdata;
586✔
412
        try
413
        {
414
            fs::directory_iterator nodir;
586✔
415
            fs::path libs_path(libs);
586✔
416

417
            std::error_code ec;
586✔
418
            if (!fs::exists(libs_path, ec) || ec)
586✔
419
                return plugin_registries;    // given directory doesn't exist
×
420

421
            // retrieve/create section [hpx.components]
422
            if (!ini.has_section("hpx.components"))
586✔
423
            {
424
                util::section* hpx_sec = ini.get_section("hpx");
×
425
                HPX_ASSERT(nullptr != hpx_sec);
×
426

427
                util::section comp_sec;
×
428
                hpx_sec->add_section("components", comp_sec);
×
429
            }
×
430

431
            // generate component sections for all found shared libraries
432
            // this will create too many sections, but the non-components will
433
            // be filtered out during loading
434
            for (fs::directory_iterator dir(libs_path); dir != nodir; ++dir)
7,618✔
435
            {
436
                fs::path curr(*dir);
7,032✔
437
                if (curr.extension() != HPX_SHARED_LIB_EXTENSION)
7,032✔
438
                    continue;
4,688✔
439

440
                // instance name and module name are the same
441
                std::string name(fs::basename(curr));    //-V821
2,344✔
442

443
#if !defined(HPX_WINDOWS)
444
                if (0 == name.find("lib"))
2,344✔
445
                    name = name.substr(3);
2,344✔
446
#endif
447
#if defined(__APPLE__)    // shared library version is added berfore extension
448
                const std::string version = hpx::full_version_as_string();
449
                std::string::size_type i = name.find(version);
450
                if (i != std::string::npos)
451
                    name.erase(
452
                        i - 1, version.length() + 1);    // - 1 for one more dot
453
#endif
454
                // ensure base directory, remove symlinks, etc.
455
                std::error_code fsec;
2,344✔
456
                fs::path canonical_curr =
457
                    fs::canonical(curr, fs::initial_path(), fsec);
2,344✔
458
                if (fsec)
2,344✔
459
                    canonical_curr = curr;
×
460

461
                // make sure every module name is loaded exactly once, the
462
                // first occurrence of a module name is used
463
                std::string basename = canonical_curr.filename().string();
2,344✔
464
                std::pair<std::map<std::string, fs::path>::iterator, bool> p =
465
                    basenames.emplace(basename, canonical_curr);
2,344✔
466

467
                if (p.second)
2,344✔
468
                {
469
                    libdata.emplace_back(canonical_curr, name);
2,344✔
470
                }
2,344✔
471
                else
472
                {
473
                    LRT_(warning).format(
×
474
                        "skipping module {} ({}): ignored because of: {}",
×
475
                        basename, canonical_curr.string(),
×
476
                        p.first->second.string());
×
477
                }
478
            }
7,032✔
479
        }
586✔
480
        catch (fs::filesystem_error const& e)
481
        {
482
            LRT_(info).format("caught filesystem error: {}", e.what());
×
483
        }
×
484

485
        // return if no new modules have been found
486
        if (libdata.empty())
586✔
487
            return plugin_registries;
×
488

489
        // make sure each node loads libraries in a different order
490
        std::random_device random_device;
586✔
491
        std::mt19937 generator(random_device());
586✔
492
        std::shuffle(libdata.begin(), libdata.end(), HPX_MOVE(generator));
586✔
493

494
        for (auto const& p : libdata)
2,930✔
495
        {
496
            LRT_(info).format("attempting to load: {}", p.first.string());
2,344✔
497

498
            // get the handle of the library
499
            error_code ec(throwmode::lightweight);
2,344✔
500
            hpx::util::plugin::dll d(p.first.string(), p.second);
2,344✔
501
            d.load_library(ec);
2,344✔
502
            if (ec)
2,344✔
503
            {
504
                LRT_(info).format("skipping (load_library failed): {}: {}",
×
505
                    p.first.string(), get_error_what(ec));
×
506
                continue;
×
507
            }
508

509
            bool must_keep_loaded = false;
2,344✔
510

511
            // get the component factory
512
            std::string curr_fullname(p.first.parent_path().string());
2,344✔
513
            load_component_factory(
2,344✔
514
                d, ini, curr_fullname, component_registries, p.second, ec);
2,344✔
515
            if (ec)
2,344✔
516
            {
517
                LRT_(info).format(
695✔
518
                    "skipping (load_component_factory failed): {}: {}",
109✔
519
                    p.first.string(), get_error_what(ec));
109✔
520
                ec = error_code(throwmode::lightweight);    // reinit ec
586✔
521
            }
586✔
522
            else
523
            {
524
                LRT_(debug).format(
2,085✔
525
                    "load_component_factory succeeded: {}", p.first.string());
327✔
526
                must_keep_loaded = true;
1,758✔
527
            }
528

529
            // get the plugin factory
530
            plugin_list_type tmp_regs =
531
                load_plugin_factory(d, ini, curr_fullname, p.second, ec);
2,344✔
532

533
            if (ec)
2,344✔
534
            {
535
                LRT_(info).format(
2,085✔
536
                    "skipping (load_plugin_factory failed): {}: {}",
327✔
537
                    p.first.string(), get_error_what(ec));
327✔
538
            }
1,758✔
539
            else
540
            {
541
                LRT_(debug).format(
695✔
542
                    "load_plugin_factory succeeded: {}", p.first.string());
109✔
543

544
                std::copy(tmp_regs.begin(), tmp_regs.end(),
586✔
545
                    std::back_inserter(plugin_registries));
586✔
546
                must_keep_loaded = true;
586✔
547
            }
548

549
            // store loaded library for future use
550
            if (must_keep_loaded)
2,344✔
551
            {
552
                modules.emplace(p.second, HPX_MOVE(d));
2,344✔
553
            }
2,344✔
554
        }
2,344✔
555
        return plugin_registries;
586✔
556
    }
586✔
557
}}    // namespace hpx::util
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