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

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

36.25
/libs/full/agas_base/src/server/symbol_namespace_server.cpp
1
//  Copyright (c) 2011 Bryce Adelstein-Lelbach
2
//  Copyright (c) 2012-2023 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/server/symbol_namespace.hpp>
11
#include <hpx/assert.hpp>
12
#include <hpx/modules/errors.hpp>
13
#include <hpx/modules/format.hpp>
14
#include <hpx/modules/thread_support.hpp>
15
#include <hpx/modules/timing.hpp>
16
#include <hpx/modules/util.hpp>
17
#include <hpx/naming/credit_handling.hpp>
18
#include <hpx/naming/split_gid.hpp>
19

20
#include <atomic>
21
#include <cstdint>
22
#include <map>
23
#include <memory>
24
#include <mutex>
25
#include <regex>
26
#include <string>
27
#include <utility>
28
#include <vector>
29

30
#include <hpx/config/warnings_prefix.hpp>
31

32
namespace hpx::agas {
33

34
    naming::gid_type bootstrap_symbol_namespace_gid()
×
35
    {
36
        return naming::gid_type(agas::symbol_ns_msb, agas::symbol_ns_lsb);
×
37
    }
38

39
    hpx::id_type bootstrap_symbol_namespace_id()
×
40
    {
41
        return {agas::symbol_ns_msb, agas::symbol_ns_lsb,
42
            hpx::id_type::management_type::unmanaged};
×
43
    }
44
}    // namespace hpx::agas
45

46
namespace hpx::agas::server {
47

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

55
        this->base_type::set_locality_id(locality_id);
32✔
56

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

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

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

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

83
    bool symbol_namespace::bind(
288✔
84
        std::string const& key, naming::gid_type const& gid_)
85
    {
86
        util::scoped_timer<std::atomic<std::int64_t>> update(
87
            counter_data_.bind_.time_, counter_data_.bind_.enabled_);
288✔
88
        counter_data_.increment_bind_count();
288✔
89

90
        std::unique_lock<mutex_type> l(mutex_);
288✔
91

92
        naming::gid_type gid = gid_;
93

94
        auto const it = gids_.find(key);
95
        if (auto const end = gids_.end(); it != end)
288✔
96
        {
97
            std::int64_t const credits =
98
                naming::detail::get_credit_from_gid(gid);
99
            naming::gid_type raw_gid = *(it->second);
100

101
            naming::detail::strip_internal_bits_from_gid(raw_gid);
102
            naming::detail::strip_internal_bits_from_gid(gid);
103

104
            // increase reference count
105
            if (raw_gid == gid)
106
            {
107
                // REVIEW: do we need to add the credit of the argument to the
108
                // table?
109
                naming::detail::add_credit_to_gid(*(it->second), credits);
×
110

111
                l.unlock();
×
112

113
                LAGAS_(info).format(
×
114
                    "symbol_namespace::bind, key({1}), gid({2}), "
115
                    "old_credit({3}), new_credit({4})",
116
                    key, gid,
117
                    naming::detail::get_credit_from_gid(*(it->second)),
×
118
                    naming::detail::get_credit_from_gid(*(it->second)) +
×
119
                        credits);
120

121
                return true;
×
122
            }
123

124
            if (LAGAS_ENABLED(info))
×
125
            {
126
                naming::detail::add_credit_to_gid(gid, credits);
×
127

128
                l.unlock();
×
129
                LAGAS_(info).format(
×
130
                    "symbol_namespace::bind, key({1}), gid({2}), "
131
                    "response(no_success)",
132
                    key, gid);
133
            }
134

135
            return false;
×
136
        }
137

138
        if (HPX_UNLIKELY(!util::insert_checked(
288✔
139
                gids_.emplace(key, std::make_shared<naming::gid_type>(gid)))))
140
        {
141
            l.unlock();
×
142

143
            HPX_THROW_EXCEPTION(hpx::error::lock_error,
×
144
                "symbol_namespace::bind",
145
                "GID table insertion failed due to a locking error or "
146
                "memory corruption");
147
        }
148

149
        // handle registered events
150
        if (auto const [first, last] = on_event_data_.equal_range(key);
288✔
151
            first != last)
152
        {
153
            std::vector<hpx::id_type> lcos;
1✔
154

155
            auto iter = first;
156
            while (iter != last)
2✔
157
            {
158
                lcos.push_back(iter->second);
1✔
159
                ++iter;
160
            }
161

162
            on_event_data_.erase(first, last);
163

164
            // notify all LCOS which were registered with this name
165
            for (hpx::id_type const& id : lcos)
2✔
166
            {
167
                // re-locate the entry in the GID table for each LCO anew, as we
168
                // need to unlock the mutex protecting the table for each
169
                // iteration below
170
                auto gid_it = gids_.find(key);
171
                if (gid_it == gids_.end())
1✔
172
                {
173
                    l.unlock();
×
174

175
                    HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
176
                        "symbol_namespace::bind",
177
                        "unable to re-locate the entry in the GID table");
178
                }
179

180
                {
181
                    // hold on to the gid while the map is unlocked
182
                    std::shared_ptr<naming::gid_type> current_gid =
183
                        gid_it->second;
184

185
                    unlock_guard<std::unique_lock<mutex_type>> ul(l);
186

187
                    // split the credit as the receiving end will expect to keep
188
                    // the object alive
189
                    naming::gid_type new_gid =
190
                        naming::detail::split_gid_if_needed(
191
                            hpx::launch::sync, *current_gid);
1✔
192

193
                    // trigger the lco
194
                    set_lco_value(id, new_gid);
195

196
                    LAGAS_(info).format(
1✔
197
                        "symbol_namespace::bind, notify: key({1}), "
198
                        "stored_gid({2}), new_gid({3})",
199
                        key, *current_gid, new_gid);
200
                }
201
            }
202
        }
1✔
203

204
        l.unlock();
288✔
205

206
        LAGAS_(info).format(
288✔
207
            "symbol_namespace::bind, key({1}), gid({2})", key, gid);
208

209
        return true;
210
    }
288✔
211

212
    naming::gid_type symbol_namespace::resolve(std::string const& key)
×
213
    {
214
        util::scoped_timer<std::atomic<std::int64_t>> update(
215
            counter_data_.resolve_.time_, counter_data_.resolve_.enabled_);
×
216
        counter_data_.increment_resolve_count();
×
217

218
        std::unique_lock<mutex_type> l(mutex_);
×
219

220
        auto const it = gids_.find(key);
221
        if (auto const end = gids_.end(); it == end)
×
222
        {
223
            l.unlock();
×
224

225
            LAGAS_(info).format(
×
226
                "symbol_namespace::resolve, key({1}), response(no_success)",
227
                key);
228

229
            return naming::invalid_gid;
230
        }
231

232
        // hold on to gid before unlocking the map
233
        std::shared_ptr<naming::gid_type> const current_gid(it->second);
234

235
        l.unlock();
×
236

237
        naming::gid_type gid = naming::detail::split_gid_if_needed(
238
            hpx::launch::sync, *current_gid);
×
239

240
        LAGAS_(info).format("symbol_namespace::resolve, key({1}), "
×
241
                            "stored_gid({2}), gid({3})",
242
            key, *current_gid, gid);
243

244
        return gid;
245
    }
×
246

247
    naming::gid_type symbol_namespace::unbind(std::string const& key)
169✔
248
    {
249
        util::scoped_timer<std::atomic<std::int64_t>> update(
250
            counter_data_.unbind_.time_, counter_data_.unbind_.enabled_);
169✔
251
        counter_data_.increment_unbind_count();
169✔
252

253
        std::unique_lock<mutex_type> l(mutex_);
169✔
254

255
        auto const it = gids_.find(key);
256
        if (auto const end = gids_.end(); it == end)
169✔
257
        {
258
            l.unlock();
×
259

260
            LAGAS_(info).format(
×
261
                "symbol_namespace::unbind, key({1}), response(no_success)",
262
                key);
263

264
            return naming::invalid_gid;
265
        }
266

267
        naming::gid_type gid = *(it->second);
268

269
        gids_.erase(it);
270

271
        l.unlock();
169✔
272

273
        LAGAS_(info).format(
169✔
274
            "symbol_namespace::unbind, key({1}), gid({2})", key, gid);
275

276
        return gid;
277
    }
169✔
278

279
    // TODO: catch exceptions
280
    symbol_namespace::iterate_names_return_type symbol_namespace::iterate(
×
281
        std::string const& pattern)
282
    {
283
        util::scoped_timer<std::atomic<std::int64_t>> update(
284
            counter_data_.iterate_names_.time_,
×
285
            counter_data_.iterate_names_.enabled_);
×
286
        counter_data_.increment_iterate_names_count();
×
287

288
        std::map<std::string, naming::gid_type> found;
289

290
        if (pattern.find_first_of("*?[]") != std::string::npos)
×
291
        {
292
            std::string const str_rx(util::regex_from_pattern(pattern, throws));
×
293
            std::regex const rx(str_rx);
×
294

295
            std::unique_lock<mutex_type> l(mutex_);
×
296
            for (auto& gid : gids_)
×
297
            {
298
                if (!std::regex_match(gid.first, rx))
×
299
                    continue;
×
300

301
                // hold on to entry while map is unlocked
302
                std::shared_ptr<naming::gid_type> current_gid(gid.second);
303
                unlock_guard<std::unique_lock<mutex_type>> ul(l);
304

305
                found[gid.first] = naming::detail::split_gid_if_needed(
×
306
                    hpx::launch::sync, *current_gid);
307
            }
308
        }
×
309
        else
310
        {
311
            std::unique_lock<mutex_type> l(mutex_);
×
312
            for (auto& gid : gids_)
×
313
            {
314
                if (!pattern.empty() && pattern != gid.first)
×
315
                    continue;
×
316

317
                // hold on to entry while map is unlocked
318
                std::shared_ptr<naming::gid_type> current_gid(gid.second);
319
                unlock_guard<std::unique_lock<mutex_type>> ul(l);
320

321
                found[gid.first] = naming::detail::split_gid_if_needed(
×
322
                    hpx::launch::sync, *current_gid);
323
            }
324
        }
325

326
        LAGAS_(info).format("symbol_namespace::iterate");
×
327

328
        return found;
×
329
    }
×
330

331
    bool symbol_namespace::on_event(std::string const& name,
8✔
332
        bool call_for_past_events, hpx::id_type const& lco)
333
    {
334
        util::scoped_timer<std::atomic<std::int64_t>> update(
335
            counter_data_.on_event_.time_, counter_data_.on_event_.enabled_);
8✔
336
        counter_data_.increment_on_event_count();
8✔
337

338
        std::unique_lock<mutex_type> l(mutex_);
8✔
339

340
        bool handled = false;
341

342
        if (call_for_past_events)
8✔
343
        {
344
            if (auto const it = gids_.find(name); it != gids_.end())
8✔
345
            {
346
                // split the credit as the receiving end will expect to keep the
347
                // object alive
348
                {
349
                    // hold on to entry while map is unlocked
350
                    std::shared_ptr<naming::gid_type> const current_gid(
351
                        it->second);
352

353
                    unlock_guard<std::unique_lock<mutex_type>> ul(l);
354
                    naming::gid_type new_gid =
355
                        naming::detail::split_gid_if_needed(
356
                            hpx::launch::sync, *current_gid);
7✔
357

358
                    // trigger the lco
359
                    handled = true;
360

361
                    // trigger LCO as name is already bound to an id
362
                    set_lco_value(lco, new_gid);
363

364
                    LAGAS_(info).format(
7✔
365
                        "symbol_namespace::on_event, notify: key({1}), "
366
                        "stored_gid({2}), new_gid({3})",
367
                        name, *current_gid, new_gid);
368
                }
369
            }
370
        }
371

372
        if (!handled)
373
        {
374
            [[maybe_unused]] auto const it = on_event_data_.emplace(name, lco);
375

376
            // This overload of insert always returns the iterator pointing
377
            // to the inserted value. It should never point to end
378
            HPX_ASSERT_LOCKED(l, it != on_event_data_.end());
379
        }
380

381
        l.unlock();
8✔
382

383
        LAGAS_(info).format("symbol_namespace::on_event: name({1})", name);
8✔
384

385
        return true;
8✔
386
    }
8✔
387

388
    // access current counter values
389
    std::int64_t symbol_namespace::counter_data::get_bind_count(bool reset)
×
390
    {
391
        return util::get_and_reset_value(bind_.count_, reset);
×
392
    }
393

394
    std::int64_t symbol_namespace::counter_data::get_resolve_count(bool reset)
×
395
    {
396
        return util::get_and_reset_value(resolve_.count_, reset);
×
397
    }
398

399
    std::int64_t symbol_namespace::counter_data::get_unbind_count(bool reset)
×
400
    {
401
        return util::get_and_reset_value(unbind_.count_, reset);
×
402
    }
403

404
    std::int64_t symbol_namespace::counter_data::get_iterate_names_count(
×
405
        bool reset)
406
    {
407
        return util::get_and_reset_value(iterate_names_.count_, reset);
×
408
    }
409

410
    std::int64_t symbol_namespace::counter_data::get_on_event_count(bool reset)
×
411
    {
412
        return util::get_and_reset_value(on_event_.count_, reset);
×
413
    }
414

415
    std::int64_t symbol_namespace::counter_data::get_overall_count(bool reset)
×
416
    {
417
        return util::get_and_reset_value(bind_.count_, reset) +
×
418
            util::get_and_reset_value(resolve_.count_, reset) +
×
419
            util::get_and_reset_value(unbind_.count_, reset) +
×
420
            util::get_and_reset_value(iterate_names_.count_, reset) +
×
421
            util::get_and_reset_value(on_event_.count_, reset);
×
422
    }
423

424
    void symbol_namespace::counter_data::enable_all()
×
425
    {
426
        bind_.enabled_ = true;
×
427
        resolve_.enabled_ = true;
×
428
        unbind_.enabled_ = true;
×
429
        iterate_names_.enabled_ = true;
×
430
        on_event_.enabled_ = true;
×
431
    }
×
432

433
    // access execution time counters
434
    std::int64_t symbol_namespace::counter_data::get_bind_time(bool reset)
×
435
    {
436
        return util::get_and_reset_value(bind_.time_, reset);
×
437
    }
438

439
    std::int64_t symbol_namespace::counter_data::get_resolve_time(bool reset)
×
440
    {
441
        return util::get_and_reset_value(resolve_.time_, reset);
×
442
    }
443

444
    std::int64_t symbol_namespace::counter_data::get_unbind_time(bool reset)
×
445
    {
446
        return util::get_and_reset_value(unbind_.time_, reset);
×
447
    }
448

449
    std::int64_t symbol_namespace::counter_data::get_iterate_names_time(
×
450
        bool reset)
451
    {
452
        return util::get_and_reset_value(iterate_names_.time_, reset);
×
453
    }
454

455
    std::int64_t symbol_namespace::counter_data::get_on_event_time(bool reset)
×
456
    {
457
        return util::get_and_reset_value(on_event_.time_, reset);
×
458
    }
459

460
    std::int64_t symbol_namespace::counter_data::get_overall_time(bool reset)
×
461
    {
462
        return util::get_and_reset_value(bind_.time_, reset) +
×
463
            util::get_and_reset_value(resolve_.time_, reset) +
×
464
            util::get_and_reset_value(unbind_.time_, reset) +
×
465
            util::get_and_reset_value(iterate_names_.time_, reset) +
×
466
            util::get_and_reset_value(on_event_.time_, reset);
×
467
    }
468

469
    // increment counter values
470
    void symbol_namespace::counter_data::increment_bind_count()
288✔
471
    {
472
        if (bind_.enabled_)
288✔
473
        {
474
            ++bind_.count_;
475
        }
476
    }
288✔
477

478
    void symbol_namespace::counter_data::increment_resolve_count()
×
479
    {
480
        if (resolve_.enabled_)
×
481
        {
482
            ++resolve_.count_;
483
        }
484
    }
×
485

486
    void symbol_namespace::counter_data::increment_unbind_count()
169✔
487
    {
488
        if (unbind_.enabled_)
169✔
489
        {
490
            ++unbind_.count_;
491
        }
492
    }
169✔
493

494
    void symbol_namespace::counter_data::increment_iterate_names_count()
×
495
    {
496
        if (iterate_names_.enabled_)
×
497
        {
498
            ++iterate_names_.count_;
499
        }
500
    }
×
501

502
    void symbol_namespace::counter_data::increment_on_event_count()
8✔
503
    {
504
        if (on_event_.enabled_)
8✔
505
        {
506
            ++on_event_.count_;
507
        }
508
    }
8✔
509
}    // 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