• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

39.84
/libs/full/agas_base/src/server/primary_namespace_server.cpp
1
//  Copyright (c) 2011 Bryce Adelstein-Lelbach
2
//  Copyright (c) 2012-2025 Hartmut Kaiser
3
//  Copyright (c) 2016 Thomas Heller
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
#include <hpx/config.hpp>
10
#include <hpx/agas_base/route.hpp>
11
#include <hpx/agas_base/server/primary_namespace.hpp>
12
#include <hpx/assert.hpp>
13
#include <hpx/components_base/agas_interface.hpp>
14
#include <hpx/format.hpp>
15
#include <hpx/modules/async_distributed.hpp>
16
#include <hpx/modules/errors.hpp>
17
#include <hpx/modules/lock_registration.hpp>
18
#include <hpx/modules/logging.hpp>
19
#include <hpx/modules/timing.hpp>
20
#include <hpx/modules/type_support.hpp>
21
#include <hpx/modules/util.hpp>
22

23
#include <atomic>
24
#include <cstdint>
25
#include <list>
26
#include <memory>
27
#include <mutex>
28
#include <sstream>
29
#include <string>
30
#include <utility>
31
#include <vector>
32

33
namespace hpx::agas {
34

35
    naming::gid_type bootstrap_primary_namespace_gid()
36
    {
×
37
        return naming::gid_type(agas::primary_ns_msb, agas::primary_ns_lsb);
38
    }
×
39

40
    hpx::id_type bootstrap_primary_namespace_id()
41
    {
×
42
        return {agas::primary_ns_msb, agas::primary_ns_lsb,
43
            hpx::id_type::management_type::unmanaged};
44
    }
×
45
}    // namespace hpx::agas
46

47
namespace hpx::agas::server {
48

49
    void primary_namespace::register_server_instance(
50
        char const* servicename, std::uint32_t locality_id, error_code& ec)
32✔
51
    {
52
        // set locality_id for this component
53
        if (locality_id == naming::invalid_locality_id)
54
            locality_id = 0;    // if not given, we're on the root
32✔
55

56
        this->base_type::set_locality_id(locality_id);
57

32✔
58
        // now register this AGAS instance with AGAS :-P
59
        instance_name_ = agas::service_name;
60
        instance_name_ += servicename;
32✔
61
        instance_name_ += agas::server::primary_namespace_service_name;
62

63
        // register a gid (not the id) to avoid AGAS holding a reference to this
64
        // component
65
        agas::register_name(
66
            launch::sync, instance_name_, get_unmanaged_id().get_gid(), ec);
32✔
67
    }
32✔
68

32✔
69
    void primary_namespace::unregister_server_instance(error_code& ec) const
70
    {
×
71
        agas::unregister_name(launch::sync, instance_name_, ec);
72
        this->base_type::finalize();
×
73
    }
×
74

×
75
    void primary_namespace::finalize() const
76
    {
×
77
        if (!instance_name_.empty())
78
        {
×
79
            error_code ec(throwmode::lightweight);
80
            agas::unregister_name(launch::sync, instance_name_, ec);
81
        }
×
82
    }
83

×
84
    // start migration of the given object
85
    std::pair<hpx::id_type, naming::address> primary_namespace::begin_migration(
86
        naming::gid_type id)
×
87
    {
88
        util::scoped_timer<std::atomic<std::int64_t>> update(
89
            counter_data_.begin_migration_.time_,
90
            counter_data_.begin_migration_.enabled_);
×
91
        counter_data_.increment_begin_migration_count();
×
92
        using hpx::get;
×
93

94
        std::unique_lock<mutex_type> l(mutex_);
95

×
96
        wait_for_migration_locked(l, id, hpx::throws);
97
        resolved_type r = resolve_gid_locked_non_local(l, id, hpx::throws);
×
98
        if (get<0>(r) == naming::invalid_gid)
×
99
        {
100
            l.unlock();
101

×
102
            LAGAS_(info).format("primary_namespace::begin_migration, gid({1}), "
103
                                "response(no_success)",
×
104
                id);
105

106
            return std::make_pair(hpx::invalid_id, naming::address());
107
        }
108

109
        auto it = migrating_objects_.find(id);
110
        if (it == migrating_objects_.end())
111
        {
×
112
            std::pair<migration_table_type::iterator, bool> const p =
113
                migrating_objects_.emplace(std::piecewise_construct,
114
                    std::forward_as_tuple(id), std::forward_as_tuple());
115
            HPX_ASSERT(p.second);
×
116
            it = p.first;
117
        }
×
118
        else
119
        {
120
            HPX_ASSERT(!hpx::get<0>(it->second));
121
        }
122

123
        // flag this id as being migrated
124
        hpx::get<0>(it->second) = true;    //-V601
125

×
126
        gva const& g(hpx::get<1>(r));
127
        naming::address addr(g.prefix, g.type, g.lva());
128
        hpx::id_type loc(
×
129
            hpx::get<2>(r), hpx::id_type::management_type::unmanaged);
130
        return std::make_pair(loc, addr);
×
131
    }
132

×
133
    // migration of the given object is complete
134
    // 26115: Failing to release lock 'this->mutex_' in function
135
#if defined(HPX_MSVC)
×
136
#pragma warning(push)
137
#pragma warning(disable : 26115)
138
#endif
×
139
    bool primary_namespace::end_migration(naming::gid_type const& id)
×
140
    {
×
141
        util::scoped_timer<std::atomic<std::int64_t>> update(
142
            counter_data_.end_migration_.time_,
×
143
            counter_data_.end_migration_.enabled_);
144
        counter_data_.increment_end_migration_count();
145

146
        std::unique_lock<mutex_type> l(mutex_);
×
147

148
        using hpx::get;
149

150
        if (auto const it = migrating_objects_.find(id);
×
151
            it != migrating_objects_.end())
×
152
        {
153
            // flag this id as not being migrated anymore
×
154
            get<0>(it->second) = false;
155
            if (get<1>(it->second) != 0)
156
            {
157
                get<2>(it->second).notify_all(HPX_MOVE(l), hpx::throws);
158
            }
159
            else
160
            {
161
                migrating_objects_.erase(it);
×
162
            }
×
163
        }
164

165
        return true;
×
166
    }
167
#if defined(HPX_MSVC)
168
#pragma warning(pop)
169
#endif
170

171
    // wait if given object is currently being migrated
172
    void primary_namespace::wait_for_migration_locked(
173
        std::unique_lock<mutex_type>& l, naming::gid_type const& id,
×
174
        error_code& ec)
175
    {
176
        HPX_ASSERT_OWNS_LOCK(l);
×
177

178
        using hpx::get;
×
179

180
        if (auto const it = migrating_objects_.find(id);
181
            it != migrating_objects_.end())
182
        {
×
183
            if (get<0>(it->second))
184
            {
185
                ++get<1>(it->second);
186

187
                get<2>(it->second).wait(l, ec);
188

189
                if (--get<1>(it->second) == 0)    //-V516
×
190
                {
191
                    migrating_objects_.erase(it);
192
                }
193
            }
194
            else
195
            {
×
196
                if (get<1>(it->second) == 0)
197
                {
160✔
198
                    migrating_objects_.erase(it);
199
                }
200
            }
201
        }
160✔
202
    }
160✔
203

204
    bool primary_namespace::bind_gid(
205
        gva const& g, naming::gid_type id, naming::gid_type const& locality)
206
    {    // {{{ bind_gid implementation
207
        util::scoped_timer<std::atomic<std::int64_t>> update(
208
            counter_data_.bind_gid_.time_, counter_data_.bind_gid_.enabled_);
160✔
209
        counter_data_.increment_bind_gid_count();
210
        using hpx::get;
211

212
        naming::gid_type const gid = id;
213
        naming::detail::strip_internal_bits_from_gid(id);
160✔
214

215
        std::unique_lock<mutex_type> l(mutex_);
216

217
        auto const begin = gvas_.begin();
218
        auto const end = gvas_.end();
219

220
        if (auto it = gvas_.lower_bound(id); it != end)
×
221
        {
222
            // If we got an exact match, this is a request to update an existing
223
            // binding (e.g. move semantics).
×
224
            if (it->first == id)
225
            {
×
226
                // non-migratable gids can't be rebound
227
                if (naming::refers_to_local_lva(gid) &&
228
                    !naming::refers_to_virtual_memory(gid))
229
                {
230
                    l.unlock();
231

×
232
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
233
                        "primary_namespace::bind_gid",
234
                        "cannot rebind gids for non-migratable objects");
235
                }
×
236

237
                gva& gaddr = it->second.first;
238
                naming::gid_type& loc = it->second.second;
×
239

240
                // Check for count mismatch (we can't change block sizes of
×
241
                // existing bindings).
242
                if (HPX_UNLIKELY(gaddr.count != g.count))
243
                {
244
                    // REVIEW: Is this the right error code to use?
245
                    l.unlock();
×
246

247
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
248
                        "primary_namespace::bind_gid",
249
                        "cannot change block size of existing binding");
×
250
                }
251

252
                if (HPX_UNLIKELY(
253
                        to_int(hpx::components::component_enum_type::invalid) ==
254
                        g.type))
255
                {
256
                    l.unlock();
×
257

258
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
259
                        "primary_namespace::bind_gid",
260
                        "attempt to update a GVA with an invalid type, "
×
261
                        "gid({1}), gva({2}), locality({3})",
262
                        id, g, locality);
263
                }
264

265
                if (HPX_UNLIKELY(!locality))
266
                {
267
                    l.unlock();
268

269
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
270
                        "primary_namespace::bind_gid",
×
271
                        "attempt to update a GVA with an invalid "
272
                        "locality id, "
×
273
                        "gid({1}), gva({2}), locality({3})",
274
                        id, g, locality);
275
                }
×
276

277
                // Store the new endpoint and offset
×
278
                gaddr.prefix = g.prefix;
279
                gaddr.type = g.type;
280
                gaddr.lva(g.lva());
281
                gaddr.offset = g.offset;
282
                loc = locality;
283

284
                l.unlock();
285

286
                LAGAS_(info).format(
287
                    "primary_namespace::bind_gid, gid({1}), gva({2}), "
93✔
288
                    "locality({3}), response(repeated_request)",
289
                    id, g, locality);
290

291
                return false;
292
            }
180✔
293

294
            // We're about to decrement the iterator it - first, we
295
            // check that it's safe to do this.
×
296
            else if (it != begin)
297
            {
×
298
                --it;
299

300
                // Check that a previous range doesn't cover the new id.
301
                if (HPX_UNLIKELY((it->first + it->second.first.count) > id))
302
                {
303
                    // REVIEW: Is this the right error code to use?
304
                    l.unlock();
67✔
305

306
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
307
                        "primary_namespace::bind_gid",
308
                        "the new GID is contained in an existing range");
309
                }
70✔
310
            }
311
        }
312

×
313
        else if (HPX_LIKELY(!gvas_.empty()))
314
        {
×
315
            --it;
316

317
            // Check that a previous range doesn't cover the new id.
318
            if ((it->first + it->second.first.count) > id)
319
            {
320
                // REVIEW: Is this the right error code to use?
321
                l.unlock();
160✔
322

323
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
324
                    "primary_namespace::bind_gid",
×
325
                    "the new GID is contained in an existing range");
326
            }
327
        }
328

329
        // non-migratable gids don't need to be bound
×
330
        if (naming::refers_to_local_lva(gid) &&
331
            !naming::refers_to_virtual_memory(gid))
332
        {
160✔
333
            LAGAS_(info).format(
334
                "primary_namespace::bind_gid, gid({1}), gva({2}), "
160✔
335
                "locality({3})",
336
                gid, g, locality);
×
337

338
            return true;
×
339
        }
340

341
        naming::gid_type const upper_bound(id + (g.count - 1));
342

343
        if (HPX_UNLIKELY(id.get_msb() != upper_bound.get_msb()))
160✔
344
        {
345
            l.unlock();
×
346

347
            HPX_THROW_EXCEPTION(hpx::error::internal_server_error,
×
348
                "primary_namespace::bind_gid",
349
                "MSBs of lower and upper range bound do not match");
350
        }
351

352
        if (HPX_UNLIKELY(
353
                to_int(hpx::components::component_enum_type::invalid) ==
354
                g.type))
355
        {
160✔
356
            l.unlock();
357

358
            HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
×
359
                "primary_namespace::bind_gid",
360
                "attempt to insert a GVA with an invalid type, "
×
361
                "gid({1}), gva({2}), locality({3})",
362
                id, g, locality);
363
        }
364

365
        // Insert a GID -> GVA entry into the GVA table.
366
        if (HPX_UNLIKELY(!util::insert_checked(
367
                gvas_.emplace(id, std::make_pair(g, locality)))))
160✔
368
        {
369
            l.unlock();
160✔
370

371
            HPX_THROW_EXCEPTION(hpx::error::lock_error,
372
                "primary_namespace::bind_gid",
373
                "GVA table insertion failed due to a locking error or "
374
                "memory corruption, gid({1}), gva({2}), locality({3})",
160✔
375
                id, g, locality);
376
        }
377

378
        l.unlock();
379

380
        LAGAS_(info).format(
381
            "primary_namespace::bind_gid, gid({1}), gva({2}), locality({3})",
382
            id, g, locality);
383

1,078✔
384
        return true;
1,057✔
385
    }    // }}}
386

387
    inline primary_namespace::resolved_type resolve_local_id(
21✔
388
        naming::gid_type const& id) noexcept
389
    {
390
        naming::gid_type locality = naming::get_locality_from_gid(id);
391
        gva addr(locality,
21✔
392
            static_cast<components::component_type>(
21✔
393
                naming::detail::get_component_type_from_gid(id.get_msb())),
21✔
394
            1, id.get_lsb());
395
        return primary_namespace::resolved_type(id, addr, locality);
396
    }
21✔
397

398
    primary_namespace::resolved_type primary_namespace::resolve_gid(
399
        naming::gid_type const& id)
21✔
400
    {    // {{{ resolve_gid implementation
401
        util::scoped_timer<std::atomic<std::int64_t>> update(
402
            counter_data_.resolve_gid_.time_,
21✔
403
            counter_data_.resolve_gid_.enabled_);
404
        counter_data_.increment_resolve_gid_count();
405
        using hpx::get;
406

×
407
        resolved_type r;
408

409
        // handle (non-migratable) components located on this locality first
×
410
        if (naming::refers_to_local_lva(id) &&
411
            !naming::refers_to_virtual_memory(id))
×
412
        {
413
            r = resolve_local_id(id);
414
        }
415
        else
×
416
        {
417
            std::unique_lock<mutex_type> l(mutex_);
418

419
            // wait for any migration to be completed
420
            if (naming::detail::is_migratable(id))
×
421
            {
422
                wait_for_migration_locked(l, id, hpx::throws);
423
            }
424

425
            // now, resolve the id
426
            r = resolve_gid_locked_non_local(l, id, hpx::throws);
427
        }
428

21✔
429
        if (get<0>(r) == naming::invalid_gid)
430
        {
431
            LAGAS_(info).format("primary_namespace::resolve_gid, gid({1}), "
432
                                "response(no_success)",
433
                id);
434

21✔
435
            return resolved_type(
436
                naming::invalid_gid, gva(), naming::invalid_gid);
×
437
        }
438

×
439
        LAGAS_(info).format(
×
440
            "primary_namespace::resolve_gid, gid({1}), base({2}), gva({3}), "
441
            "locality_id({4})",
442
            id, get<0>(r), get<1>(r), get<2>(r));
1,253✔
443

444
        return r;
445
    }    // }}}
446

1,253✔
447
    hpx::id_type primary_namespace::colocate(naming::gid_type const& id)
1,253✔
448
    {
1,253✔
449
        return {hpx::get<2>(resolve_gid(id)),
450
            hpx::id_type::management_type::unmanaged};
451
    }
452

1,253✔
453
    naming::address primary_namespace::unbind_gid(
454
        std::uint64_t count, naming::gid_type id)
455
    {    // {{{ unbind_gid implementation
1,253✔
456
        util::scoped_timer<std::atomic<std::int64_t>> update(
457
            counter_data_.unbind_gid_.time_,
125✔
458
            counter_data_.unbind_gid_.enabled_);
459
        counter_data_.increment_unbind_gid_count();
×
460

461
        naming::detail::strip_internal_bits_from_gid(id);
×
462

463
        std::unique_lock<mutex_type> l(mutex_);
464

465
        auto const it = gvas_.find(id);
466
        if (auto const end = gvas_.end(); it != end)
467
        {
468
            if (HPX_UNLIKELY(it->second.first.count != count))
469
            {
125✔
470
                l.unlock();
125✔
471

472
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
473
                    "primary_namespace::unbind_gid", "block sizes must match");
474
            }
475

476
            gva_table_data_type const data = it->second;
477

478
            gvas_.erase(it);
479

480
            l.unlock();
1,128✔
481
            LAGAS_(info).format(
482
                "primary_namespace::unbind_gid, gid({1}), count({2}), "
483
                "gva({3}), locality_id({4})",
484
                id, count, data.first, data.second);
485

486
            gva g = data.first;
487
            return {g.prefix, g.type, g.lva()};
1,064✔
488
        }
489

1,064✔
490
        // non-migratable gids are not bound
491
        if (naming::refers_to_local_lva(id) &&
492
            !naming::refers_to_virtual_memory(id))
493
        {
494
            naming::gid_type const locality = naming::get_locality_from_gid(id);
1,064✔
495
            gva g(locality,
496
                static_cast<components::component_type>(
497
                    naming::detail::get_component_type_from_gid(id.get_msb())),
64✔
498
                0, id.get_lsb());
499

64✔
500
            LAGAS_(info).format(
501
                "primary_namespace::unbind_gid, gid({1}), count({2}), "
502
                "gva({3}), locality({4})",
503
                id, count, g, g.prefix);
504

64✔
505
            return {g.prefix, g.type, g.lva()};
1,253✔
506
        }
507

28✔
508
        l.unlock();
509

510
        LAGAS_(info).format(
511
            "primary_namespace::unbind_gid, gid({1}), count({2}), "
28✔
512
            "response(no_success)",
28✔
513
            id, count);
28✔
514

515
        return {};
516
    }    // }}}
517

518
    std::int64_t primary_namespace::increment_credit(
519
        std::int64_t credits, naming::gid_type lower, naming::gid_type upper)
28✔
520
    {    // increment_credit implementation
521
        util::scoped_timer<std::atomic<std::int64_t>> update(
522
            counter_data_.increment_credit_.time_,
28✔
523
            counter_data_.increment_credit_.enabled_);
524
        counter_data_.increment_increment_credit_count();
28✔
525

28✔
526
        naming::detail::strip_internal_bits_from_gid(lower);
527
        naming::detail::strip_internal_bits_from_gid(upper);
528

×
529
        if (lower == upper)
530
            ++upper;
531

28✔
532
        // Increment.
533
        if (credits > 0)
122✔
534
        {
535
            increment(lower, upper, credits, hpx::throws);
536
            return credits;
537
        }
538

122✔
539
        HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
122✔
540
            "primary_namespace::increment_credit",
122✔
541
            "invalid credit count of {1}", credits);
542
    }
122✔
543

122✔
544
    std::vector<std::int64_t> primary_namespace::decrement_credit(
545
        std::vector<hpx::tuple<std::int64_t, naming::gid_type,
1,249✔
546
            naming::gid_type>> const& requests)
547
    {    // decrement_credit implementation
1,127✔
548
        util::scoped_timer<std::atomic<std::int64_t>> update(
549
            counter_data_.decrement_credit_.time_,
550
            counter_data_.decrement_credit_.enabled_);
551
        counter_data_.increment_decrement_credit_count();
552

553
        std::vector<int64_t> res_credits;
554
        res_credits.reserve(requests.size());
555

1,127✔
556
        for (auto& req : requests)
557
        {
558
            std::int64_t credits = hpx::get<0>(req);
1,127✔
559
            naming::gid_type lower = hpx::get<1>(req);
560
            naming::gid_type upper = hpx::get<1>(req);
561

1,127✔
562
            naming::detail::strip_internal_bits_from_gid(lower);
563
            naming::detail::strip_internal_bits_from_gid(upper);
1,127✔
564

565
            if (lower == upper)
566
                ++upper;
567

×
568
            // Decrement.
569
            if (credits < 0)
570
            {
571
                free_entry_list_type free_list;
1,127✔
572
                decrement_sweep(free_list, lower, upper, -credits, hpx::throws);
573

574
                free_components_sync(free_list, lower, upper, hpx::throws);
122✔
575
            }
122✔
576
            else
577
            {
32✔
578
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
579
                    "primary_namespace::decrement_credit",
580
                    "invalid credit count of {1}", credits);
581
            }
32✔
582
            res_credits.push_back(credits);
32✔
583
        }
584

585
        return res_credits;
32✔
586
    }
587

×
588
    std::pair<naming::gid_type, naming::gid_type> primary_namespace::allocate(
589
        std::uint64_t count)
590
    {    // {{{ allocate implementation
×
591
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
592
            counter_data_.allocate_.time_, counter_data_.allocate_.enabled_);
593
        counter_data_.increment_allocate_count();
594

595
        // Just return the prefix
596
        if (count == 0)
32✔
597
        {
598
            LAGAS_(info).format(
599
                "primary_namespace::allocate, count({1}), lower({1}), "
32✔
600
                "upper({3}), prefix({4}), response(repeated_request)",
601
                count, next_id_, next_id_,
602
                naming::get_locality_id_from_gid(next_id_));
603

32✔
604
            return std::make_pair(next_id_, next_id_);
605
        }
606

607
        std::uint64_t const real_count = count - 1;
×
608

609
        // Compute the new allocation.
610
        naming::gid_type lower(next_id_ + 1);
611
        naming::gid_type upper(lower + real_count);
×
612

613
        // Check for overflow.
614
        if (upper.get_msb() != lower.get_msb())
615
        {
616
            // Check for address space exhaustion (we currently use 86 bits of
617
            // the gid for the actual id)
618
            if (HPX_UNLIKELY(
×
619
                    (lower.get_msb() & naming::gid_type::virtual_memory_mask) ==
620
                    naming::gid_type::virtual_memory_mask))
621
            {
622
                HPX_THROW_EXCEPTION(hpx::error::internal_server_error,
623
                    "locality_namespace::allocate",
624
                    "primary namespace has been exhausted");
625
            }
626

627
            // Otherwise, correct
628
            lower = naming::gid_type(upper.get_msb(), nullptr);
629
            upper = lower + real_count;
630
        }
32✔
631

632
        // Store the new upper bound.
633
        next_id_ = upper;
634

635
        // Set the initial credit count.
636
        naming::detail::set_credit_for_gid(
32✔
637
            lower, static_cast<std::int64_t>(HPX_GLOBALCREDIT_INITIAL));
638
        naming::detail::set_credit_for_gid(
639
            upper, static_cast<std::int64_t>(HPX_GLOBALCREDIT_INITIAL));
640

641
        LAGAS_(info).format(
642
            "primary_namespace::allocate, count({1}), lower({2}), upper({3}), "
643
            "response(success)",
644
            count, lower, upper);
645

646
        return std::make_pair(lower, upper);
647
    }    // }}}
648

649
#if defined(HPX_HAVE_AGAS_DUMP_REFCNT_ENTRIES)
650
    void primary_namespace::dump_refcnt_matches(
651
        refcnt_table_type::iterator lower_it,
652
        refcnt_table_type::iterator upper_it, naming::gid_type const& lower,
653
        naming::gid_type const& upper, std::unique_lock<mutex_type>& l,
654
        char const* func_name)
655
    {
656
        // dump_refcnt_matches implementation
657
        HPX_ASSERT(l.owns_lock());
658

659
        if (lower_it == refcnts_.end() && upper_it == refcnts_.end())
660
            // We got nothing, bail - our caller is probably about to throw.
661
            return;
662

663
        std::stringstream ss;
664
        hpx::util::format_to(ss,
665
            "{1}, dumping server-side refcnt table matches, lower({2}), "
666
            "upper({3}):",
667
            func_name, lower, upper);
668

669
        for (/**/; lower_it != upper_it; ++lower_it)
670
        {
671
            // The [server] tag is in there to make it easier to filter
28✔
672
            // through the logs.
673
            hpx::util::format_to(ss, "\n  [server] lower({1}), credits({2})",
674
                lower_it->first, lower_it->second);
675
        }
28✔
676

677
        LAGAS_(debug) << ss.str();
678
    }    // dump_refcnt_matches implementation
679
#endif
680

681
    ///////////////////////////////////////////////////////////////////////////////
682
    void primary_namespace::increment(naming::gid_type const& lower,
683
        naming::gid_type const& upper, std::int64_t const& credits,
684
        error_code& ec)
685
    {    // {{{ increment implementation
686
        std::unique_lock<mutex_type> l(mutex_);
687

688
#if defined(HPX_HAVE_AGAS_DUMP_REFCNT_ENTRIES)
689
        if (LAGAS_ENABLED(debug))
690
        {
691
            typedef refcnt_table_type::iterator iterator;
692

693
            // Find the mappings that we're about to touch.
694
            refcnt_table_type::iterator lower_it = refcnts_.find(lower);
695
            refcnt_table_type::iterator upper_it;
696
            if (lower != upper)
697
            {
698
                upper_it = refcnts_.find(upper);
699
            }
700
            else
701
            {
702
                upper_it = lower_it;
703
                ++upper_it;
704
            }
705

706
            dump_refcnt_matches(lower_it, upper_it, lower, upper, l,
707
                "primary_namespace::increment");
708
        }
709
#endif
710

28✔
711
        // TODO: Whine loudly if a reference count overflows. We reserve ~0 for
712
        // internal bookkeeping in the decrement algorithm, so the maximum global
713
        // reference count is 2^64 - 2. The maximum number of credits a single GID
28✔
714
        // can hold, however, is limited to 2^32 - 1.
715

13✔
716
        // The third parameter we pass here is the default data to use in case the
13✔
717
        // key is not mapped. We don't insert GIDs into the refcnt table when we
13✔
718
        // allocate/bind them, so if a GID is not in the refcnt table, we know that
719
        // it's global reference count is the initial global reference count.
720

13✔
721
        for (naming::gid_type raw = lower; raw != upper; ++raw)
13✔
722
        {
723
            auto it = refcnts_.find(raw);
×
724
            if (it == refcnts_.end())
725
            {
×
726
                std::int64_t count =
727
                    static_cast<std::int64_t>(HPX_GLOBALCREDIT_INITIAL) +
728
                    credits;
729

730
                std::pair<refcnt_table_type::iterator, bool> const p =
×
731
                    refcnts_.insert(refcnt_table_type::value_type(raw, count));
732
                if (!p.second)
733
                {
13✔
734
                    l.unlock();
735

736
                    HPX_THROWS_IF(ec, hpx::error::invalid_data,
737
                        "primary_namespace::increment",
15✔
738
                        "couldn't create entry in reference count table, "
739
                        "raw({1}), ref-count({2})",
740
                        raw, count);
28✔
741
                    return;
742
                }
×
743

744
                it = p.first;
745
            }
28✔
746
            else
×
747
            {
748
                it->second += credits;
749
            }
750

1,127✔
751
            LAGAS_(info).format(
752
                "primary_namespace::increment, raw({1}), refcnt({2})", lower,
753
                it->second);
754
        }
755

756
        if (&ec != &throws)
757
            ec = make_success_code();
758
    }    // }}}
759

760
    ///////////////////////////////////////////////////////////////////////////////
761
    // 26110: Caller failing to hold lock 'l' before calling function
762
#if defined(HPX_MSVC)
2,184✔
763
#pragma warning(push)
764
#pragma warning(disable : 26110)
765
#endif
766
    void primary_namespace::resolve_free_list(std::unique_lock<mutex_type>& l,
767
        std::list<refcnt_table_type::iterator> const& free_list,
768
        free_entry_list_type& free_entry_list,
769
        naming::gid_type const& /* lower */,
1,057✔
770
        naming::gid_type const& /* upper */, error_code& ec)
771
    {
772
        HPX_ASSERT_OWNS_LOCK(l);
×
773

774
        using hpx::get;
775

776
        using iterator = refcnt_table_type::iterator;
1,057✔
777

1,057✔
778
        for (iterator const& it : free_list)
×
779
        {
780
            using key_type = refcnt_table_type::key_type;
781

782
            // The mapping's key space.
783
            key_type gid = it->first;
×
784

785
            if (naming::detail::is_migratable(gid))
×
786
            {
787
                // wait for any migration to be completed
788
                wait_for_migration_locked(l, gid, ec);
789
            }
790

×
791
            // Resolve the query GID.
792
            resolved_type r = resolve_gid_locked(l, gid, ec);
793
            if (ec)
794
                return;
795

796
            naming::gid_type& raw = get<0>(r);
797
            if (raw == naming::invalid_gid)
1,057✔
798
            {
799
                l.unlock();
×
800

801
                HPX_THROWS_IF(ec, hpx::error::internal_server_error,
×
802
                    "primary_namespace::resolve_free_list",
803
                    "primary_namespace::resolve_free_list, failed to resolve "
804
                    "gid, gid({1})",
805
                    gid);
806
                return;    // couldn't resolve this one
×
807
            }
808

1,057✔
809
            // Make sure the GVA is valid.
810
            gva& g = get<1>(r);
×
811

812
            // REVIEW: Should we do more to make sure the GVA is valid?
×
813
            if (HPX_UNLIKELY(
814
                    to_int(hpx::components::component_enum_type::invalid) ==
815
                    g.type))
816
            {
817
                l.unlock();
×
818

819
                HPX_THROWS_IF(ec, hpx::error::internal_server_error,
820
                    "primary_namespace::resolve_free_list",
1,057✔
821
                    "encountered a GVA with an invalid type while performing a "
822
                    "decrement, gid({1}), gva({2})",
823
                    gid, g);
824
                return;
825
            }
826
            else if (HPX_UNLIKELY(0 == g.count))
827
            {
828
                l.unlock();
829

830
                HPX_THROWS_IF(ec, hpx::error::internal_server_error,
831
                    "primary_namespace::resolve_free_list",
832
                    "encountered a GVA with a count of zero while performing a "
833
                    "decrement, gid({1}), gva({2})",
834
                    gid, g);
835
                return;
836
            }
837

838
            LAGAS_(info).format(
1,127✔
839
                "primary_namespace::resolve_free_list, resolved match, "
840
                "gid({1}), gva({2})",
841
                gid, g);
842

1,127✔
843
            // Fully resolve the range.
844
            gva const resolved = g.resolve(gid, raw);
845

846
            // Add the information needed to destroy these components to the
847
            // free list.
848
            free_entry_list.emplace_back(resolved, gid, get<2>(r));
849

850
            // remove this entry from the refcnt table
1,127✔
851
            refcnts_.erase(it);
852
        }
853
    }
854
#if defined(HPX_MSVC)
855
#pragma warning(pop)
856
#endif
857

858
    ///////////////////////////////////////////////////////////////////////////////
859
    void primary_namespace::decrement_sweep(
860
        free_entry_list_type& free_entry_list, naming::gid_type const& lower,
861
        naming::gid_type const& upper, std::int64_t credits, error_code& ec)
862
    {    // {{{ decrement_sweep implementation
863
        LAGAS_(info).format(
864
            "primary_namespace::decrement_sweep, lower({1}), upper({2}), "
865
            "credits({3})",
866
            lower, upper, credits);
867

868
        free_entry_list.clear();
869

870
        {
871
            std::unique_lock<mutex_type> l(mutex_);
872

873
#if defined(HPX_HAVE_AGAS_DUMP_REFCNT_ENTRIES)
874
            if (LAGAS_ENABLED(debug))
875
            {
876
                typedef refcnt_table_type::iterator iterator;
877

878
                // Find the mappings that we just added or modified.
879
                refcnt_table_type::iterator lower_it = refcnts_.find(lower);
880
                refcnt_table_type::iterator upper_it;
881
                if (lower != upper)
882
                {
883
                    upper_it = refcnts_.find(upper);
884
                }
885
                else
1,127✔
886
                {
887
                    upper_it = lower_it;
1,127✔
888
                    ++upper_it;
1,127✔
889
                }
890

1,044✔
891
                dump_refcnt_matches(lower_it, upper_it, lower, upper, l,
892
                    "primary_namespace::decrement_sweep");
893
            }
×
894
#endif
895

×
896
            ///////////////////////////////////////////////////////////////////////
897
            // Apply the decrement across the entire key space (e.g. [lower, upper]).
898

899
            // The third parameter we pass here is the default data to use in case
900
            // the key is not mapped. We don't insert GIDs into the refcnt table
901
            // when we allocate/bind them, so if a GID is not in the refcnt table,
902
            // we know that it's global reference count is the initial global
903
            // reference count.
×
904

905
            std::list<refcnt_table_type::iterator> free_list;    //-V826
906
            for (naming::gid_type raw = lower; raw != upper; ++raw)
1,044✔
907
            {
1,044✔
908
                auto it = refcnts_.find(raw);
909
                if (it == refcnts_.end())
910
                {
911
                    if (credits >
1,044✔
912
                        static_cast<std::int64_t>(HPX_GLOBALCREDIT_INITIAL))
1,044✔
913
                    {
914
                        l.unlock();
×
915

916
                        HPX_THROWS_IF(ec, hpx::error::invalid_data,
×
917
                            "primary_namespace::decrement_sweep",
918
                            "negative entry in reference count table, "
919
                            "raw({1}), refcount({2})",
920
                            raw,
921
                            static_cast<std::int64_t>(
×
922
                                HPX_GLOBALCREDIT_INITIAL) -
923
                                credits);
924
                        return;
1,044✔
925
                    }
926

927
                    std::int64_t count =
928
                        static_cast<std::int64_t>(HPX_GLOBALCREDIT_INITIAL) -
83✔
929
                        credits;
930

931
                    std::pair<refcnt_table_type::iterator, bool> const p =
932
                        refcnts_.emplace(raw, count);
1,127✔
933
                    if (!p.second)
934
                    {
×
935
                        l.unlock();
936

×
937
                        HPX_THROWS_IF(ec, hpx::error::invalid_data,
938
                            "primary_namespace::decrement_sweep",
939
                            "couldn't create entry in reference count table, "
940
                            "raw({1}), ref-count({2})",
941
                            raw, count);
×
942
                        return;
943
                    }
944

945
                    it = p.first;
1,127✔
946
                }
947
                else
948
                {
949
                    it->second -= credits;
950
                }
1,127✔
951

952
                // Sanity check.
953
                if (it->second < 0)
954
                {
1,127✔
955
                    l.unlock();
×
956

957
                    HPX_THROWS_IF(ec, hpx::error::invalid_data,
958
                        "primary_namespace::decrement_sweep",
959
                        "negative entry in reference count table, raw({1}), "
1,127✔
960
                        "refcount({2})",
961
                        raw, it->second);
962
                    return;
963
                }
964

965
                // this objects needs to be deleted
966
                if (it->second == 0)
967
                    free_list.push_back(it);
2,184✔
968
            }
969

970
            // Resolve the objects which have to be deleted.
1,057✔
971
            resolve_free_list(l, free_list, free_entry_list, lower, upper, ec);
972

973
        }    // Unlock the mutex.
×
974

975
        if (&ec != &throws)
976
            ec = make_success_code();
977
    }
×
978

×
979
    ///////////////////////////////////////////////////////////////////////////////
980
    void primary_namespace::free_components_sync(
981
        free_entry_list_type const& free_list, naming::gid_type const& lower,
1,057✔
982
        naming::gid_type const& upper, error_code& ec) const
983
    {
984
        using hpx::get;
×
985

986
        ///////////////////////////////////////////////////////////////////////////
987
        // Delete the objects on the free list.
988
        for (free_entry const& e : free_list)
1,057✔
989
        {
990
            // Bail if we're in late shutdown and non-local.
991
            if (HPX_UNLIKELY(!threads::threadmanager_is(hpx::state::running)) &&
1,057✔
992
                e.locality_ != locality_)
1,057✔
993
            {
994
                LAGAS_(info).format(
×
995
                    "primary_namespace::free_components_sync, cancelling free "
996
                    "operation because the threadmanager is down, lower({1}), "
997
                    "upper({2}), base({3}), gva({4}), locality({5})",
998
                    lower, upper, e.gid_, e.gva_, e.locality_);
999
                continue;
×
1000
            }
1001

1,057✔
1002
            LAGAS_(info).format(
1003
                "primary_namespace::free_components_sync, freeing component, "
1004
                "lower({1}), upper({2}), base({3}), gva({4}), locality({5})",
1005
                lower, upper, e.gid_, e.gva_, e.locality_);
×
1006

1007
            // Destroy the component.
1008
            HPX_ASSERT(e.locality_ == e.gva_.prefix);
1009
            naming::address addr(e.locality_, e.gva_.type, e.gva_.lva());
1,127✔
1010
            if (e.locality_ == locality_)
×
1011
            {
1012
                auto const deleter = components::deleter(e.gva_.type);
1013
                if (deleter == nullptr)
1,057✔
1014
                {
1015
                    HPX_THROWS_IF(ec, hpx::error::internal_server_error,
1016
                        "primary_namespace::free_components_sync",
1017
                        "Attempting to delete object of unknown component "
1018
                        "type: " +
1019
                            std::to_string(e.gva_.type));
1020
                    return;
1,057✔
1021
                }
1022
                deleter(e.gid_, HPX_MOVE(addr));
1023
            }
1,057✔
1024
            else
×
1025
            {
1026
                agas::destroy_component(e.gid_, addr);
1027
            }
1028
        }
1029

×
1030
        if (&ec != &throws)
1031
            ec = make_success_code();
1032
    }
1033

×
1034
    primary_namespace::resolved_type primary_namespace::resolve_gid_locked(
1035
        std::unique_lock<mutex_type>& l, naming::gid_type const& gid,
1036
        error_code& ec)
1037
    {
1038
        HPX_ASSERT_OWNS_LOCK(l);
1039

1040
        // handle (non-migratable) components located on this locality first
1041
        if (naming::refers_to_local_lva(gid) &&
1042
            !naming::refers_to_virtual_memory(gid))
1043
        {
1044
            if (&ec != &throws)
1045
                ec = make_success_code();
1046

1047
            return resolve_local_id(gid);
1048
        }
1049

×
1050
        return resolve_gid_locked_non_local(l, gid, ec);
1051
    }
1052

1053
    // 26110: Caller failing to hold lock 'l' before calling function
1054
#if defined(HPX_MSVC)
×
1055
#pragma warning(push)
×
1056
#pragma warning(disable : 26110)
1057
#endif
1058
    primary_namespace::resolved_type
1059
    primary_namespace::resolve_gid_locked_non_local(
1060
        std::unique_lock<mutex_type>& l, naming::gid_type const& gid,
1061
        error_code& ec)
1062
    {
1063
        HPX_ASSERT_OWNS_LOCK(l);
×
1064

1065
        HPX_ASSERT(!(naming::refers_to_local_lva(gid) &&
1066
            !naming::refers_to_virtual_memory(gid)));
1067

1068
        // parameters
1069
        naming::gid_type id = gid;
×
1070
        naming::detail::strip_internal_bits_from_gid(id);
1071

×
1072
        gva_table_type::const_iterator it = gvas_.lower_bound(id);
1073
        gva_table_type::const_iterator const begin = gvas_.begin();
×
1074

1075
        if (gva_table_type::const_iterator const end = gvas_.end(); it != end)
×
1076
        {
1077
            // Check for exact match
1078
            if (it->first == id)
1079
            {
1080
                if (&ec != &throws)
1081
                    ec = make_success_code();
1082

1083
                gva_table_data_type const& data = it->second;
×
1084
                return resolved_type(it->first, data.first, data.second);
×
1085
            }
1086

1087
            // We need to decrement the iterator, first we check that it's safe
1088
            // to do this.
1089
            if (it != begin)
1090
            {
1091
                --it;
×
1092

1093
                // Found the GID in a range
1094
                gva_table_data_type const& data = it->second;
1095
                if ((it->first + data.first.count) > id)
1096
                {
1097
                    if (HPX_UNLIKELY(id.get_msb() != it->first.get_msb()))
×
1098
                    {
1099
                        l.unlock();
×
1100

1101
                        HPX_THROWS_IF(ec, hpx::error::internal_server_error,
×
1102
                            "primary_namespace::resolve_gid_locked",
1103
                            "MSBs of lower and upper range bound do not "
×
1104
                            "match");
1105
                        return resolved_type(
1106
                            naming::invalid_gid, gva(), naming::invalid_gid);
1107
                    }
1108

1109
                    if (&ec != &throws)
1110
                        ec = make_success_code();
×
1111

×
1112
                    return resolved_type(it->first, data.first, data.second);
1113
                }
1114
            }
1115
        }
1116

1117
        else if (HPX_LIKELY(!gvas_.empty()))
×
1118
        {
×
1119
            --it;
1120

1121
            // Found the GID in a range
1122
            gva_table_data_type const& data = it->second;
1123
            if ((it->first + data.first.count) > id)
1124
            {
1125
                if (HPX_UNLIKELY(id.get_msb() != it->first.get_msb()))
1126
                {
×
1127
                    l.unlock();
1128

1129
                    HPX_THROWS_IF(ec, hpx::error::internal_server_error,
×
1130
                        "primary_namespace::resolve_gid_locked",
×
1131
                        "MSBs of lower and upper range bound do not match");
1132
                    return resolved_type(
×
1133
                        naming::invalid_gid, gva(), naming::invalid_gid);
×
1134
                }
1135

1136
                if (&ec != &throws)
1137
                    ec = make_success_code();
×
1138

1139
                return resolved_type(it->first, data.first, data.second);
×
1140
            }
1141
        }
1142

×
1143
        if (&ec != &throws)
1144
            ec = make_success_code();
1145

×
1146
        return resolved_type(naming::invalid_gid, gva(), naming::invalid_gid);
1147
    }
1148
#if defined(HPX_MSVC)
×
1149
#pragma warning(pop)
1150
#endif
1151

×
1152
#if defined(HPX_HAVE_NETWORKING)
1153
    void (*route)(primary_namespace& server, parcelset::parcel&& p) = nullptr;
1154

×
1155
    void primary_namespace::route(parcelset::parcel&& p)
1156
    {
1157
        util::scoped_timer<std::atomic<std::int64_t>> update(
×
1158
            counter_data_.route_.time_, counter_data_.route_.enabled_);
1159
        counter_data_.increment_route_count();
1160

×
1161
        (*server::route)(*this, HPX_MOVE(p));
1162
    }
1163
#endif
×
1164

1165
    // access current counter values
1166
    std::int64_t primary_namespace::counter_data::get_bind_gid_count(bool reset)
×
1167
    {
1168
        return util::get_and_reset_value(bind_gid_.count_, reset);
×
1169
    }
1170

1171
    std::int64_t primary_namespace::counter_data::get_resolve_gid_count(
×
1172
        bool reset)
1173
    {
1174
        return util::get_and_reset_value(resolve_gid_.count_, reset);
×
1175
    }
1176

1177
    std::int64_t primary_namespace::counter_data::get_unbind_gid_count(
×
1178
        bool reset)
1179
    {
1180
        return util::get_and_reset_value(unbind_gid_.count_, reset);
×
1181
    }
1182

1183
    std::int64_t primary_namespace::counter_data::get_increment_credit_count(
×
1184
        bool reset)
1185
    {
1186
        return util::get_and_reset_value(increment_credit_.count_, reset);
1187
    }
×
1188

1189
    std::int64_t primary_namespace::counter_data::get_decrement_credit_count(
×
1190
        bool reset)
×
1191
    {
×
1192
        return util::get_and_reset_value(decrement_credit_.count_, reset);
×
1193
    }
×
1194

×
1195
    std::int64_t primary_namespace::counter_data::get_allocate_count(bool reset)
×
1196
    {
×
1197
        return util::get_and_reset_value(allocate_.count_, reset);
1198
    }
1199

1200
    std::int64_t primary_namespace::counter_data::get_begin_migration_count(
×
1201
        bool reset)
1202
    {
×
1203
        return util::get_and_reset_value(begin_migration_.count_, reset);
1204
    }
1205

×
1206
    std::int64_t primary_namespace::counter_data::get_end_migration_count(
1207
        bool reset)
1208
    {
×
1209
        return util::get_and_reset_value(end_migration_.count_, reset);
1210
    }
1211

×
1212
    std::int64_t primary_namespace::counter_data::get_overall_count(bool reset)
1213
    {
1214
        return
×
1215
#if defined(HPX_HAVE_NETWORKING)
1216
            util::get_and_reset_value(route_.count_, reset) +
1217
#endif
×
1218
            util::get_and_reset_value(bind_gid_.count_, reset) +
1219
            util::get_and_reset_value(resolve_gid_.count_, reset) +
1220
            util::get_and_reset_value(unbind_gid_.count_, reset) +
×
1221
            util::get_and_reset_value(increment_credit_.count_, reset) +
1222
            util::get_and_reset_value(decrement_credit_.count_, reset) +
1223
            util::get_and_reset_value(allocate_.count_, reset) +
×
1224
            util::get_and_reset_value(begin_migration_.count_, reset) +
1225
            util::get_and_reset_value(end_migration_.count_, reset);
1226
    }
×
1227

1228
    // access execution time counters
1229
    std::int64_t primary_namespace::counter_data::get_bind_gid_time(bool reset)
×
1230
    {
1231
        return util::get_and_reset_value(bind_gid_.time_, reset);
×
1232
    }
1233

1234
    std::int64_t primary_namespace::counter_data::get_resolve_gid_time(
×
1235
        bool reset)
1236
    {
1237
        return util::get_and_reset_value(resolve_gid_.time_, reset);
×
1238
    }
1239

1240
    std::int64_t primary_namespace::counter_data::get_unbind_gid_time(
×
1241
        bool reset)
1242
    {
1243
        return util::get_and_reset_value(unbind_gid_.time_, reset);
×
1244
    }
1245

1246
    std::int64_t primary_namespace::counter_data::get_increment_credit_time(
×
1247
        bool reset)
1248
    {
1249
        return util::get_and_reset_value(increment_credit_.time_, reset);
1250
    }
×
1251

1252
    std::int64_t primary_namespace::counter_data::get_decrement_credit_time(
×
1253
        bool reset)
×
1254
    {
×
1255
        return util::get_and_reset_value(decrement_credit_.time_, reset);
×
1256
    }
×
1257

×
1258
    std::int64_t primary_namespace::counter_data::get_allocate_time(bool reset)
×
1259
    {
×
1260
        return util::get_and_reset_value(allocate_.time_, reset);
1261
    }
1262

×
1263
    std::int64_t primary_namespace::counter_data::get_begin_migration_time(
1264
        bool reset)
1265
    {
×
1266
        return util::get_and_reset_value(begin_migration_.time_, reset);
1267
    }
×
1268

×
1269
    std::int64_t primary_namespace::counter_data::get_end_migration_time(
×
1270
        bool reset)
×
1271
    {
×
1272
        return util::get_and_reset_value(end_migration_.time_, reset);
×
1273
    }
×
1274

×
1275
    std::int64_t primary_namespace::counter_data::get_overall_time(bool reset)
×
1276
    {
1277
        return
1278
#if defined(HPX_HAVE_NETWORKING)
160✔
1279
            util::get_and_reset_value(route_.time_, reset) +
1280
#endif
160✔
1281
            util::get_and_reset_value(bind_gid_.time_, reset) +
1282
            util::get_and_reset_value(resolve_gid_.time_, reset) +
1283
            util::get_and_reset_value(unbind_gid_.time_, reset) +
1284
            util::get_and_reset_value(increment_credit_.time_, reset) +
160✔
1285
            util::get_and_reset_value(decrement_credit_.time_, reset) +
1286
            util::get_and_reset_value(allocate_.time_, reset) +
21✔
1287
            util::get_and_reset_value(begin_migration_.time_, reset) +
1288
            util::get_and_reset_value(end_migration_.time_, reset);
21✔
1289
    }
1290

1291
    void primary_namespace::counter_data::enable_all()
1292
    {
21✔
1293
#if defined(HPX_HAVE_NETWORKING)
1294
        route_.enabled_ = true;
1,253✔
1295
#endif
1296
        bind_gid_.enabled_ = true;
1,253✔
1297
        resolve_gid_.enabled_ = true;
1298
        unbind_gid_.enabled_ = true;
1299
        increment_credit_.enabled_ = true;
1300
        decrement_credit_.enabled_ = true;
1,253✔
1301
        allocate_.enabled_ = true;
1302
        begin_migration_.enabled_ = true;
28✔
1303
        end_migration_.enabled_ = true;
1304
    }
28✔
1305

1306
    // increment counter values
1307
    void primary_namespace::counter_data::increment_bind_gid_count()
1308
    {
28✔
1309
        if (bind_gid_.enabled_)
1310
        {
122✔
1311
            ++bind_gid_.count_;
1312
        }
122✔
1313
    }
1314

1315
    void primary_namespace::counter_data::increment_resolve_gid_count()
1316
    {
122✔
1317
        if (resolve_gid_.enabled_)
1318
        {
32✔
1319
            ++resolve_gid_.count_;
1320
        }
32✔
1321
    }
1322

1323
    void primary_namespace::counter_data::increment_unbind_gid_count()
1324
    {
32✔
1325
        if (unbind_gid_.enabled_)
1326
        {
×
1327
            ++unbind_gid_.count_;
1328
        }
×
1329
    }
1330

1331
    void primary_namespace::counter_data::increment_increment_credit_count()
1332
    {
×
1333
        if (increment_credit_.enabled_)
1334
        {
×
1335
            ++increment_credit_.count_;
1336
        }
×
1337
    }
1338

1339
    void primary_namespace::counter_data::increment_decrement_credit_count()
1340
    {
×
1341
        if (decrement_credit_.enabled_)
1342
        {
1343
            ++decrement_credit_.count_;
×
1344
        }
1345
    }
×
1346

1347
    void primary_namespace::counter_data::increment_allocate_count()
1348
    {
×
1349
        if (allocate_.enabled_)
1350
        {
×
1351
            ++allocate_.count_;
1352
        }
1353
    }
×
1354

1355
    void primary_namespace::counter_data::increment_begin_migration_count()
×
1356
    {
1357
        if (begin_migration_.enabled_)
1358
        {
1359
            ++begin_migration_.count_;
×
1360
        }
1361
    }
1362

1363
    void primary_namespace::counter_data::increment_end_migration_count()
1364
    {
1365
        if (end_migration_.enabled_)
1366
        {
1367
            ++end_migration_.count_;
1368
        }
1369
    }
1370

1371
#if defined(HPX_HAVE_NETWORKING)
1372
    std::int64_t primary_namespace::counter_data::get_route_count(bool reset)
1373
    {
1374
        return util::get_and_reset_value(route_.count_, reset);
1375
    }
1376

1377
    std::int64_t primary_namespace::counter_data::get_route_time(bool reset)
1378
    {
1379
        return util::get_and_reset_value(route_.time_, reset);
1380
    }
1381

1382
    void primary_namespace::counter_data::increment_route_count()
1383
    {
1384
        if (route_.enabled_)
1385
        {
1386
            ++route_.count_;
1387
        }
1388
    }
1389
#endif
1390
}    // 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

© 2025 Coveralls, Inc