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

STEllAR-GROUP / hpx / #853

19 Dec 2022 01:01AM UTC coverage: 86.287% (+0.4%) from 85.912%
#853

push

StellarBot
Merge #6109

6109: Modernize serialization module r=hkaiser a=hkaiser

- flyby separate serialization of Boost types

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

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

53 of 53 new or added lines in 6 files covered. (100.0%)

173939 of 201582 relevant lines covered (86.29%)

1931657.12 hits per line

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

27.8
/libs/full/agas_base/src/server/component_namespace_server.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//  Copyright (c) 2011 Bryce Adelstein-Lelbach
3
//  Copyright (c) 2012-2017 Hartmut Kaiser
4
//
5
//  SPDX-License-Identifier: BSL-1.0
6
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
7
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
////////////////////////////////////////////////////////////////////////////////
9

10
#include <hpx/config.hpp>
11
#include <hpx/agas_base/server/component_namespace.hpp>
12
#include <hpx/assert.hpp>
13
#include <hpx/async_distributed/continuation.hpp>
14
#include <hpx/components_base/agas_interface.hpp>
15
#include <hpx/modules/format.hpp>
16
#include <hpx/naming/credit_handling.hpp>
17
#include <hpx/timing/scoped_timer.hpp>
18
#include <hpx/util/get_and_reset_value.hpp>
19
#include <hpx/util/insert_checked.hpp>
20

21
#include <atomic>
22
#include <cstddef>
23
#include <cstdint>
24
#include <mutex>
25
#include <string>
26
#include <utility>
27
#include <vector>
28

29
// TODO: Remove the use of the name "prefix"
30

31
namespace hpx { namespace agas {
32

33
    naming::gid_type bootstrap_component_namespace_gid()
×
34
    {
35
        return naming::gid_type(agas::component_ns_msb, agas::component_ns_lsb);
×
36
    }
37

38
    hpx::id_type bootstrap_component_namespace_id()
×
39
    {
40
        return hpx::id_type(agas::component_ns_msb, agas::component_ns_lsb,
×
41
            hpx::id_type::management_type::unmanaged);
42
    }
43
}}    // namespace hpx::agas
44

45
namespace hpx { namespace agas { namespace server {
46

47
    void component_namespace::register_server_instance(
451✔
48
        char const* servicename, error_code& ec)
49
    {
50
        // now register this AGAS instance with AGAS :-P
51
        instance_name_ = agas::service_name;
451✔
52
        instance_name_ += servicename;
451✔
53
        instance_name_ += agas::server::component_namespace_service_name;
451✔
54

55
        // register a gid (not the id) to avoid AGAS holding a reference to this
56
        // component
57
        agas::register_name(
451✔
58
            launch::sync, instance_name_, get_unmanaged_id().get_gid(), ec);
451✔
59
    }
451✔
60

61
    void component_namespace::unregister_server_instance(error_code& ec)
451✔
62
    {
63
        agas::unregister_name(launch::sync, instance_name_, ec);
451✔
64
        this->base_type::finalize();
451✔
65
    }
451✔
66

67
    void component_namespace::finalize()
×
68
    {
69
        if (!instance_name_.empty())
×
70
        {
71
            error_code ec(throwmode::lightweight);
×
72
            agas::unregister_name(launch::sync, instance_name_, ec);
×
73
        }
×
74
    }
×
75

76
    components::component_type component_namespace::bind_prefix(
13,437✔
77
        std::string const& key, std::uint32_t prefix)
78
    {    // {{{ bind_prefix implementation
79
        util::scoped_timer<std::atomic<std::int64_t>> update(
13,437✔
80
            counter_data_.bind_prefix_.time_,
13,437✔
81
            counter_data_.bind_prefix_.enabled_);
13,437✔
82
        counter_data_.increment_bind_prefix_count();
13,437✔
83

84
        std::unique_lock<mutex_type> l(mutex_);
13,437✔
85

86
        auto cit = component_ids_.find(key);
13,437✔
87
        auto const cend = component_ids_.end();
13,437✔
88

89
        // This is the first request, so we use the type counter, and then
90
        // increment it.
91
        if (component_ids_.find(key) == cend)
13,437✔
92
        {
93
            if (HPX_UNLIKELY(!util::insert_checked(
9,488✔
94
                    component_ids_.insert(std::make_pair(key, type_counter)),
95
                    cit)))
96
            {
97
                l.unlock();
×
98

99
                HPX_THROW_EXCEPTION(hpx::error::lock_error,
×
100
                    "component_namespace::bind_prefix",
101
                    "component id table insertion failed due to a locking "
102
                    "error or memory corruption");
103
                return components::component_invalid;
104
            }
105

106
            // If the insertion succeeded, we need to increment the type
107
            // counter.
108
            ++type_counter;
9,488✔
109
        }
9,488✔
110

111
        factory_table_type::iterator fit = factories_.find(cit->second),
13,437✔
112
                                     fend = factories_.end();
13,437✔
113

114
        if (fit != fend)
13,437✔
115
        {
116
            prefixes_type& prefixes = fit->second;
3,949✔
117
            prefixes_type::iterator pit = prefixes.find(prefix);
3,949✔
118

119
            if (pit != prefixes.end())
3,949✔
120
            {
121
                // Duplicate type registration for this locality.
122
                l.unlock();
×
123

124
                HPX_THROW_EXCEPTION(hpx::error::duplicate_component_id,
×
125
                    "component_namespace::bind_prefix",
126
                    "component id is already registered for the given "
127
                    "locality, key({1}), prefix({2}), ctype({3})",
128
                    key, prefix, cit->second);
129
                return components::component_invalid;
130
            }
131

132
            fit->second.insert(prefix);
3,949✔
133

134
            // First registration for this locality, we still return no_success to
135
            // convey the fact that another locality already registered this
136
            // component type.
137
            LAGAS_(info).format(
3,949✔
138
                "component_namespace::bind_prefix, key({1}), prefix({2}), "
×
139
                "ctype({3}), response(no_success)",
140
                key, prefix, cit->second);
×
141

142
            return cit->second;
3,949✔
143
        }
144

145
        // Instead of creating a temporary and then inserting it, we insert
146
        // an empty set, then put the prefix into said set. This should
147
        // prevent a copy, though most compilers should be able to optimize
148
        // this without our help.
149
        if (HPX_UNLIKELY(!util::insert_checked(
9,488✔
150
                factories_.insert(std::make_pair(cit->second, prefixes_type())),
151
                fit)))
152
        {
153
            l.unlock();
×
154

155
            HPX_THROW_EXCEPTION(hpx::error::lock_error,
×
156
                "component_namespace::bind_prefix",
157
                "factory table insertion failed due to a locking "
158
                "error or memory corruption");
159
            return components::component_invalid;
160
        }
161

162
        fit->second.insert(prefix);
9,488✔
163

164
        LAGAS_(info).format(
9,488✔
165
            "component_namespace::bind_prefix, key({1}), prefix({2}), "
×
166
            "ctype({3})",
167
            key, prefix, cit->second);
×
168

169
        return cit->second;
9,488✔
170
    }    // }}}
13,437✔
171

172
    components::component_type component_namespace::bind_name(
11,198✔
173
        std::string const& key)
174
    {    // {{{ bind_name implementation
175
        util::scoped_timer<std::atomic<std::int64_t>> update(
11,198✔
176
            counter_data_.bind_name_.time_, counter_data_.bind_name_.enabled_);
11,198✔
177
        counter_data_.increment_bind_name_count();
11,198✔
178

179
        std::unique_lock<mutex_type> l(mutex_);
11,198✔
180

181
        auto it = component_ids_.find(key);
11,198✔
182
        auto const end = component_ids_.end();
11,198✔
183

184
        // If the name is not in the table, register it (this is only done so
185
        // we can implement a backwards compatible get_component_id).
186
        if (it == end)
11,198✔
187
        {
188
            if (HPX_UNLIKELY(!util::insert_checked(
351✔
189
                    component_ids_.insert(std::make_pair(key, type_counter)),
190
                    it)))
191
            {
192
                l.unlock();
×
193

194
                HPX_THROW_EXCEPTION(hpx::error::lock_error,
×
195
                    "component_namespace::bind_name",
196
                    "component id table insertion failed due to a locking "
197
                    "error or memory corruption");
198
                return components::component_invalid;
199
            }
200

201
            // If the insertion succeeded, we need to increment the type
202
            // counter.
203
            ++type_counter;
351✔
204
        }
351✔
205

206
        LAGAS_(info).format(
11,198✔
207
            "component_namespace::bind_name, key({1}), ctype({2})", key,
×
208
            it->second);
×
209

210
        return it->second;
11,198✔
211
    }    // }}}
11,198✔
212

213
    std::vector<std::uint32_t> component_namespace::resolve_id(
15✔
214
        components::component_type key)
215
    {    // {{{ resolve_id implementation
216
        util::scoped_timer<std::atomic<std::int64_t>> update(
15✔
217
            counter_data_.resolve_id_.time_,
15✔
218
            counter_data_.resolve_id_.enabled_);
15✔
219
        counter_data_.increment_resolve_id_count();
15✔
220

221
        // If the requested component type is a derived type, use only its derived
222
        // part for the lookup.
223
        if (key != components::get_base_type(key))
15✔
224
            key = components::get_derived_type(key);
×
225

226
        std::lock_guard<mutex_type> l(mutex_);
15✔
227

228
        factory_table_type::const_iterator it = factories_.find(key),
15✔
229
                                           end = factories_.end();
15✔
230

231
        // REVIEW: Should we differentiate between these two cases? Should we
232
        // throw an exception if it->second.empty()? It should be impossible.
233
        if (it == end || it->second.empty())
15✔
234
        {
235
            LAGAS_(info).format(
×
236
                "component_namespace::resolve_id, key({1}), localities(0)",
×
237
                key);
238

239
            return std::vector<std::uint32_t>();
×
240
        }
241

242
        else
243
        {
244
            prefixes_type const& prefixes = it->second;
15✔
245

246
            std::vector<std::uint32_t> p;
15✔
247
            p.assign(prefixes.cbegin(), prefixes.cend());
15✔
248

249
            LAGAS_(info).format(
15✔
250
                "component_namespace::resolve_id, key({1}), localities({2})",
×
251
                key, prefixes.size());
×
252

253
            return p;
15✔
254
        }
15✔
255
    }    // }}}
15✔
256

257
    bool component_namespace::unbind(std::string const& key)
×
258
    {    // {{{ unbind implementation
259
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
260
            counter_data_.unbind_name_.time_,
×
261
            counter_data_.unbind_name_.enabled_);
×
262
        counter_data_.increment_unbind_name_count();
×
263

264
        std::lock_guard<mutex_type> l(mutex_);
×
265

266
        auto const it = component_ids_.find(key);
×
267

268
        // REVIEW: Should this be an error?
269
        if (it == component_ids_.end())
×
270
        {
271
            LAGAS_(info).format(
×
272
                "component_namespace::unbind, key({1}), response(no_success)",
×
273
                key);
×
274

275
            return false;
×
276
        }
277

278
        // REVIEW: If there are no localities with this type, should we throw
279
        // an exception here?
280
        factories_.erase(it->second);
×
281
        component_ids_.erase(it);
×
282

283
        LAGAS_(info).format("component_namespace::unbind, key({1})", key);
×
284

285
        return true;
×
286
    }    // }}}
×
287

288
    // TODO: catch exceptions
289
    void component_namespace::iterate_types(
×
290
        iterate_types_function_type const& f)
291
    {    // {{{ iterate implementation
292
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
293
            counter_data_.iterate_types_.time_,
×
294
            counter_data_.iterate_types_.enabled_);
×
295
        counter_data_.increment_iterate_types_count();
×
296

297
        using value_type = std::pair<typename component_id_table_type::key_type,
298
            typename component_id_table_type::mapped_type>;
299
        std::vector<value_type> types;
×
300
        {
301
            std::lock_guard<mutex_type> l(mutex_);
×
302

303
            types.assign(component_ids_.cbegin(), component_ids_.cend());
×
304
        }
×
305

306
        for (auto&& type : types)
×
307
        {
308
            f(type.first, type.second);
×
309
        }
310

311
        LAGAS_(info).format("component_namespace::iterate_types");
×
312
    }    // }}}
×
313

314
    static std::string get_component_name(
×
315
        component_namespace::component_id_table_type const& m,
316
        components::component_type t)
317
    {
318
        if (t < components::component_last)
×
319
            return components::get_component_type_name(t);
×
320

321
        for (auto const& c : m)
×
322
        {
323
            if (c.second == t)
×
324
                return c.first;
×
325
        }
326
        return "";
×
327
    }
×
328

329
    std::string component_namespace::get_component_type_name(
×
330
        components::component_type t)
331
    {    // {{{ get_component_type_name implementation
332
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
333
            counter_data_.get_component_type_name_.time_,
×
334
            counter_data_.get_component_type_name_.enabled_);
×
335
        counter_data_.increment_get_component_type_name_count();
×
336

337
        std::lock_guard<mutex_type> l(mutex_);
×
338

339
        std::string result;
×
340

341
        if (t == components::component_invalid)
×
342
        {
343
            result = "component_invalid";
×
344
        }
×
345
        else if (components::get_derived_type(t) == 0)
×
346
        {
347
            result = get_component_name(component_ids_, t);
×
348
        }
×
349
        else if (components::get_derived_type(t) != 0)
×
350
        {
351
            result = get_component_name(
×
352
                component_ids_, components::get_derived_type(t));
×
353
            result += "/";
×
354
            result += get_component_name(
×
355
                component_ids_, components::get_base_type(t));
×
356
        }
×
357

358
        if (result.empty())
×
359
        {
360
            LAGAS_(info).format(
×
361
                "component_namespace::get_component_typename, key({1}/{2}), "
×
362
                "response(no_success)",
363
                int(components::get_derived_type(t)),
×
364
                int(components::get_base_type(t)));
×
365

366
            return result;
×
367
        }
368

369
        LAGAS_(info).format(
×
370
            "component_namespace::get_component_typename, key({1}/{2}), "
×
371
            "response({3})",
372
            int(components::get_derived_type(t)),
×
373
            int(components::get_base_type(t)), result);
×
374

375
        return result;
×
376
    }    // }}}
×
377

378
    std::uint32_t component_namespace::get_num_localities(
×
379
        components::component_type key)
380
    {    // {{{ get_num_localities implementation
381
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
382
            counter_data_.num_localities_.time_,
×
383
            counter_data_.num_localities_.enabled_);
×
384
        counter_data_.increment_num_localities_count();
×
385

386
        // If the requested component type is a derived type, use only its derived
387
        // part for the lookup.
388
        if (key != components::get_base_type(key))
×
389
            key = components::get_derived_type(key);
×
390

391
        std::lock_guard<mutex_type> l(mutex_);
×
392

393
        factory_table_type::const_iterator it = factories_.find(key),
×
394
                                           end = factories_.end();
×
395
        if (it == end)
×
396
        {
397
            LAGAS_(info).format(
×
398
                "component_namespace::get_num_localities, key({1}), "
×
399
                "localities(0)",
400
                key);
401

402
            return std::uint32_t(0);
×
403
        }
404

405
        std::uint32_t num_localities =
×
406
            static_cast<std::uint32_t>(it->second.size());
×
407

408
        LAGAS_(info).format(
×
409
            "component_namespace::get_num_localities, key({1}), "
×
410
            "localities({2})",
411
            key, num_localities);
412

413
        return num_localities;
×
414
    }    // }}}
×
415

416
    // access current counter values
417
    std::int64_t component_namespace::counter_data::get_bind_prefix_count(
×
418
        bool reset)
419
    {
420
        return util::get_and_reset_value(bind_prefix_.count_, reset);
×
421
    }
422

423
    std::int64_t component_namespace::counter_data::get_bind_name_count(
×
424
        bool reset)
425
    {
426
        return util::get_and_reset_value(bind_name_.count_, reset);
×
427
    }
428

429
    std::int64_t component_namespace::counter_data::get_resolve_id_count(
×
430
        bool reset)
431
    {
432
        return util::get_and_reset_value(resolve_id_.count_, reset);
×
433
    }
434

435
    std::int64_t component_namespace::counter_data::get_unbind_name_count(
×
436
        bool reset)
437
    {
438
        return util::get_and_reset_value(unbind_name_.count_, reset);
×
439
    }
440

441
    std::int64_t component_namespace::counter_data::get_iterate_types_count(
×
442
        bool reset)
443
    {
444
        return util::get_and_reset_value(iterate_types_.count_, reset);
×
445
    }
446

447
    std::int64_t
448
    component_namespace::counter_data ::get_component_type_name_count(
×
449
        bool reset)
450
    {
451
        return util::get_and_reset_value(
×
452
            get_component_type_name_.count_, reset);
×
453
    }
454

455
    std::int64_t component_namespace::counter_data::get_num_localities_count(
×
456
        bool reset)
457
    {
458
        return util::get_and_reset_value(num_localities_.count_, reset);
×
459
    }
460

461
    std::int64_t component_namespace::counter_data::get_overall_count(
×
462
        bool reset)
463
    {
464
        return util::get_and_reset_value(bind_prefix_.count_, reset) +
×
465
            util::get_and_reset_value(bind_name_.count_, reset) +
×
466
            util::get_and_reset_value(resolve_id_.count_, reset) +
×
467
            util::get_and_reset_value(unbind_name_.count_, reset) +
×
468
            util::get_and_reset_value(iterate_types_.count_, reset) +
×
469
            util::get_and_reset_value(get_component_type_name_.count_, reset) +
×
470
            util::get_and_reset_value(num_localities_.count_, reset);
×
471
    }
472

473
    void component_namespace::counter_data::enable_all()
×
474
    {
475
        bind_prefix_.enabled_ = true;
×
476
        bind_name_.enabled_ = true;
×
477
        resolve_id_.enabled_ = true;
×
478
        unbind_name_.enabled_ = true;
×
479
        iterate_types_.enabled_ = true;
×
480
        get_component_type_name_.enabled_ = true;
×
481
        num_localities_.enabled_ = true;
×
482
    }
×
483

484
    // access execution time counters
485
    std::int64_t component_namespace::counter_data::get_bind_prefix_time(
×
486
        bool reset)
487
    {
488
        return util::get_and_reset_value(bind_prefix_.time_, reset);
×
489
    }
490

491
    std::int64_t component_namespace::counter_data::get_bind_name_time(
×
492
        bool reset)
493
    {
494
        return util::get_and_reset_value(bind_name_.time_, reset);
×
495
    }
496

497
    std::int64_t component_namespace::counter_data::get_resolve_id_time(
×
498
        bool reset)
499
    {
500
        return util::get_and_reset_value(resolve_id_.time_, reset);
×
501
    }
502

503
    std::int64_t component_namespace::counter_data::get_unbind_name_time(
×
504
        bool reset)
505
    {
506
        return util::get_and_reset_value(unbind_name_.time_, reset);
×
507
    }
508

509
    std::int64_t component_namespace::counter_data::get_iterate_types_time(
×
510
        bool reset)
511
    {
512
        return util::get_and_reset_value(iterate_types_.time_, reset);
×
513
    }
514

515
    std::int64_t
516
    component_namespace::counter_data ::get_component_type_name_time(bool reset)
×
517
    {
518
        return util::get_and_reset_value(get_component_type_name_.time_, reset);
×
519
    }
520

521
    std::int64_t component_namespace::counter_data::get_num_localities_time(
×
522
        bool reset)
523
    {
524
        return util::get_and_reset_value(num_localities_.time_, reset);
×
525
    }
526

527
    std::int64_t component_namespace::counter_data::get_overall_time(bool reset)
×
528
    {
529
        return util::get_and_reset_value(bind_prefix_.time_, reset) +
×
530
            util::get_and_reset_value(bind_name_.time_, reset) +
×
531
            util::get_and_reset_value(resolve_id_.time_, reset) +
×
532
            util::get_and_reset_value(unbind_name_.time_, reset) +
×
533
            util::get_and_reset_value(iterate_types_.time_, reset) +
×
534
            util::get_and_reset_value(get_component_type_name_.time_, reset) +
×
535
            util::get_and_reset_value(num_localities_.time_, reset);
×
536
    }
537

538
    // increment counter values
539
    void component_namespace::counter_data::increment_bind_prefix_count()
13,437✔
540
    {
541
        if (bind_prefix_.enabled_)
13,437✔
542
        {
543
            ++bind_prefix_.count_;
×
544
        }
×
545
    }
13,437✔
546

547
    void component_namespace::counter_data::increment_bind_name_count()
11,198✔
548
    {
549
        if (bind_name_.enabled_)
11,198✔
550
        {
551
            ++bind_name_.count_;
×
552
        }
×
553
    }
11,198✔
554

555
    void component_namespace::counter_data::increment_resolve_id_count()
15✔
556
    {
557
        if (resolve_id_.enabled_)
15✔
558
        {
559
            ++resolve_id_.count_;
×
560
        }
×
561
    }
15✔
562

563
    void component_namespace::counter_data::increment_unbind_name_count()
×
564
    {
565
        if (unbind_name_.enabled_)
×
566
        {
567
            ++unbind_name_.count_;
×
568
        }
×
569
    }
×
570

571
    void component_namespace::counter_data::increment_iterate_types_count()
×
572
    {
573
        if (iterate_types_.enabled_)
×
574
        {
575
            ++iterate_types_.count_;
×
576
        }
×
577
    }
×
578

579
    void
580
    component_namespace::counter_data::increment_get_component_type_name_count()
×
581
    {
582
        if (get_component_type_name_.enabled_)
×
583
        {
584
            ++get_component_type_name_.count_;
×
585
        }
×
586
    }
×
587

588
    void component_namespace::counter_data::increment_num_localities_count()
×
589
    {
590
        if (num_localities_.enabled_)
×
591
        {
592
            ++num_localities_.count_;
×
593
        }
×
594
    }
×
595

596
}}}    // namespace hpx::agas::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

© 2026 Coveralls, Inc