• 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

49.21
/libs/full/agas_base/src/server/symbol_namespace_server.cpp
1
//  Copyright (c) 2011 Bryce Adelstein-Lelbach
2
//  Copyright (c) 2012-2021 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/async_distributed/base_lco_with_value.hpp>
13
#include <hpx/async_distributed/detail/post.hpp>
14
#include <hpx/functional/bind_back.hpp>
15
#include <hpx/functional/bind_front.hpp>
16
#include <hpx/modules/errors.hpp>
17
#include <hpx/modules/format.hpp>
18
#include <hpx/naming/credit_handling.hpp>
19
#include <hpx/naming/split_gid.hpp>
20
#include <hpx/thread_support/unlock_guard.hpp>
21
#include <hpx/timing/scoped_timer.hpp>
22
#include <hpx/type_support/unused.hpp>
23
#include <hpx/util/get_and_reset_value.hpp>
24
#include <hpx/util/insert_checked.hpp>
25
#include <hpx/util/regex_from_pattern.hpp>
26

27
#include <atomic>
28
#include <cstddef>
29
#include <cstdint>
30
#include <map>
31
#include <memory>
32
#include <mutex>
33
#include <regex>
34
#include <string>
35
#include <utility>
36
#include <vector>
37

38
namespace hpx { namespace agas {
39

40
    naming::gid_type bootstrap_symbol_namespace_gid()
×
41
    {
42
        return naming::gid_type(agas::symbol_ns_msb, agas::symbol_ns_lsb);
×
43
    }
44

45
    hpx::id_type bootstrap_symbol_namespace_id()
×
46
    {
47
        return hpx::id_type(agas::symbol_ns_msb, agas::symbol_ns_lsb,
×
48
            hpx::id_type::management_type::unmanaged);
49
    }
50
}}    // namespace hpx::agas
51

52
namespace hpx { namespace agas { namespace server {
53

54
    void symbol_namespace::register_server_instance(
593✔
55
        char const* servicename, std::uint32_t locality_id, error_code& ec)
56
    {
57
        // set locality_id for this component
58
        if (locality_id == naming::invalid_locality_id)
593✔
59
            locality_id = 0;    // if not given, we're on the root
×
60

61
        this->base_type::set_locality_id(locality_id);
593✔
62

63
        // now register this AGAS instance with AGAS :-P
64
        instance_name_ = agas::service_name;
593✔
65
        instance_name_ += servicename;
593✔
66
        instance_name_ += agas::server::symbol_namespace_service_name;
593✔
67

68
        // register a gid (not the id) to avoid AGAS holding a reference to this
69
        // component
70
        agas::register_name(
593✔
71
            launch::sync, instance_name_, get_unmanaged_id().get_gid(), ec);
593✔
72
    }
593✔
73

74
    void symbol_namespace::unregister_server_instance(error_code& ec)
592✔
75
    {
76
        agas::unregister_name(launch::sync, instance_name_, ec);
592✔
77
        this->base_type::finalize();
592✔
78
    }
592✔
79

80
    void symbol_namespace::finalize()
×
81
    {
82
        if (!instance_name_.empty())
×
83
        {
84
            error_code ec(throwmode::lightweight);
×
85
            agas::unregister_name(launch::sync, instance_name_, ec);
×
86
        }
×
87
    }
×
88

89
    bool symbol_namespace::bind(std::string key, naming::gid_type gid)
7,659✔
90
    {    // {{{ bind implementation
91
        // parameters
92
        util::scoped_timer<std::atomic<std::int64_t>> update(
7,659✔
93
            counter_data_.bind_.time_, counter_data_.bind_.enabled_);
7,659✔
94
        counter_data_.increment_bind_count();
7,659✔
95

96
        std::unique_lock<mutex_type> l(mutex_);
7,659✔
97

98
        gid_table_type::iterator it = gids_.find(key);
7,659✔
99
        gid_table_type::iterator end = gids_.end();
7,659✔
100

101
        if (it != end)
7,659✔
102
        {
103
            std::int64_t const credits =
2✔
104
                naming::detail::get_credit_from_gid(gid);
2✔
105
            naming::gid_type raw_gid = *(it->second);
2✔
106

107
            naming::detail::strip_internal_bits_from_gid(raw_gid);
2✔
108
            naming::detail::strip_internal_bits_from_gid(gid);
2✔
109

110
            // increase reference count
111
            if (raw_gid == gid)
2✔
112
            {
113
                // REVIEW: do we need to add the credit of the argument to the table?
114
                naming::detail::add_credit_to_gid(*(it->second), credits);
×
115

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

125
                return true;
×
126
            }
127

128
            if (LAGAS_ENABLED(info))
2✔
129
            {
130
                naming::detail::add_credit_to_gid(gid, credits);
×
131

132
                l.unlock();
×
133
                LAGAS_(info).format(
×
134
                    "symbol_namespace::bind, key({1}), gid({2}), "
×
135
                    "response(no_success)",
136
                    key, gid);
137
            }
×
138

139
            return false;
2✔
140
        }
141

142
        if (HPX_UNLIKELY(!util::insert_checked(gids_.insert(
7,657✔
143
                std::make_pair(key, std::make_shared<naming::gid_type>(gid))))))
144
        {
145
            l.unlock();
×
146

147
            HPX_THROW_EXCEPTION(hpx::error::lock_error,
×
148
                "symbol_namespace::bind",
149
                "GID table insertion failed due to a locking error or "
150
                "memory corruption");
151
        }
152

153
        // handle registered events
154
        typedef on_event_data_map_type::iterator iterator;
155
        std::pair<iterator, iterator> p = on_event_data_.equal_range(key);
7,657✔
156

157
        std::vector<hpx::id_type> lcos;
7,657✔
158
        if (p.first != p.second)
7,657✔
159
        {
160
            iterator it = p.first;
773✔
161
            while (it != p.second)
10,889✔
162
            {
163
                lcos.push_back((*it).second);
10,116✔
164
                ++it;
10,116✔
165
            }
166

167
            on_event_data_.erase(p.first, p.second);
773✔
168

169
            // notify all LCOS which were registered with this name
170
            for (hpx::id_type const& id : lcos)
10,889✔
171
            {
172
                // re-locate the entry in the GID table for each LCO anew, as we
173
                // need to unlock the mutex protecting the table for each iteration
174
                // below
175
                gid_table_type::iterator gid_it = gids_.find(key);
10,116✔
176
                if (gid_it == gids_.end())
10,116✔
177
                {
178
                    l.unlock();
×
179

180
                    HPX_THROW_EXCEPTION(hpx::error::invalid_status,
×
181
                        "symbol_namespace::bind",
182
                        "unable to re-locate the entry in the GID table");
183
                }
184

185
                // hold on to the gid while the map is unlocked
186
                std::shared_ptr<naming::gid_type> current_gid = gid_it->second;
10,116✔
187

188
                {
189
                    unlock_guard<std::unique_lock<mutex_type>> ul(l);
10,116✔
190

191
                    // split the credit as the receiving end will expect to keep the
192
                    // object alive
193
                    naming::gid_type new_gid =
194
                        naming::detail::split_gid_if_needed(*current_gid).get();
10,116✔
195

196
                    // trigger the lco
197
                    set_lco_value(id, new_gid);
10,116✔
198

199
                    LAGAS_(info).format(
10,116✔
200
                        "symbol_namespace::bind, notify: key({1}), "
×
201
                        "stored_gid({2}), new_gid({3})",
202
                        key, *current_gid, new_gid);
×
203
                }
10,116✔
204
            }
10,116✔
205
        }
773✔
206

207
        l.unlock();
7,657✔
208

209
        LAGAS_(info).format(
7,657✔
210
            "symbol_namespace::bind, key({1}), gid({2})", key, gid);
×
211

212
        return true;
7,657✔
213
    }    // }}}
7,659✔
214

215
    naming::gid_type symbol_namespace::resolve(std::string const& key)
114✔
216
    {    // {{{ resolve implementation
217
        // parameters
218
        util::scoped_timer<std::atomic<std::int64_t>> update(
114✔
219
            counter_data_.resolve_.time_, counter_data_.resolve_.enabled_);
114✔
220
        counter_data_.increment_resolve_count();
114✔
221

222
        std::unique_lock<mutex_type> l(mutex_);
114✔
223

224
        gid_table_type::iterator it = gids_.find(key);
114✔
225
        gid_table_type::iterator end = gids_.end();
114✔
226

227
        if (it == end)
114✔
228
        {
229
            LAGAS_(info).format(
63✔
230
                "symbol_namespace::resolve, key({1}), response(no_success)",
×
231
                key);
×
232

233
            return naming::invalid_gid;
63✔
234
        }
235

236
        // hold on to gid before unlocking the map
237
        std::shared_ptr<naming::gid_type> current_gid(it->second);
51✔
238

239
        l.unlock();
51✔
240

241
        naming::gid_type gid =
242
            naming::detail::split_gid_if_needed(*current_gid).get();
51✔
243

244
        LAGAS_(info).format(
51✔
245
            "symbol_namespace::resolve, key({1}), stored_gid({2}), gid({3})",
×
246
            key, *current_gid, gid);
×
247

248
        return gid;
51✔
249
    }    // }}}
114✔
250

251
    naming::gid_type symbol_namespace::unbind(std::string const& key)
3,420✔
252
    {    // {{{ unbind implementation
253
        util::scoped_timer<std::atomic<std::int64_t>> update(
3,420✔
254
            counter_data_.unbind_.time_, counter_data_.unbind_.enabled_);
3,420✔
255
        counter_data_.increment_unbind_count();
3,420✔
256

257
        std::unique_lock<mutex_type> l(mutex_);
3,420✔
258

259
        gid_table_type::iterator it = gids_.find(key);
3,420✔
260
        gid_table_type::iterator end = gids_.end();
3,420✔
261

262
        if (it == end)
3,420✔
263
        {
264
            LAGAS_(info).format(
×
265
                "symbol_namespace::unbind, key({1}), response(no_success)",
×
266
                key);
×
267

268
            return naming::invalid_gid;
×
269
        }
270

271
        naming::gid_type const gid = *(it->second);
3,420✔
272

273
        gids_.erase(it);
3,420✔
274

275
        l.unlock();
3,420✔
276

277
        LAGAS_(info).format(
3,420✔
278
            "symbol_namespace::unbind, key({1}), gid({2})", key, gid);
×
279

280
        return gid;
3,420✔
281
    }    // }}}
3,420✔
282

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

292
        std::map<std::string, naming::gid_type> found;
×
293

294
        if (pattern.find_first_of("*?[]") != std::string::npos)
×
295
        {
296
            std::string str_rx(util::regex_from_pattern(pattern, throws));
×
297
            std::regex rx(str_rx);
×
298

299
            std::unique_lock<mutex_type> l(mutex_);
×
300
            for (gid_table_type::iterator it = gids_.begin(); it != gids_.end();
×
301
                 ++it)
×
302
            {
303
                if (!std::regex_match(it->first, rx))
×
304
                    continue;
×
305

306
                // hold on to entry while map is unlocked
307
                std::shared_ptr<naming::gid_type> current_gid(it->second);
×
308
                unlock_guard<std::unique_lock<mutex_type>> ul(l);
×
309

310
                found[it->first] =
×
311
                    naming::detail::split_gid_if_needed(*current_gid).get();
×
312
            }
×
313
        }
×
314
        else
315
        {
316
            std::unique_lock<mutex_type> l(mutex_);
×
317
            for (gid_table_type::iterator it = gids_.begin(); it != gids_.end();
×
318
                 ++it)
×
319
            {
320
                if (!pattern.empty() && pattern != it->first)
×
321
                    continue;
×
322

323
                // hold on to entry while map is unlocked
324
                std::shared_ptr<naming::gid_type> current_gid(it->second);
×
325
                unlock_guard<std::unique_lock<mutex_type>> ul(l);
×
326

327
                found[it->first] =
×
328
                    naming::detail::split_gid_if_needed(*current_gid).get();
×
329
            }
×
330
        }
×
331

332
        LAGAS_(info).format("symbol_namespace::iterate");
×
333

334
        return found;
×
335
    }    // }}}
×
336

337
    bool symbol_namespace::on_event(
61,782✔
338
        std::string const& name, bool call_for_past_events, hpx::id_type lco)
339
    {    // {{{ on_event implementation
340
        util::scoped_timer<std::atomic<std::int64_t>> update(
61,782✔
341
            counter_data_.on_event_.time_, counter_data_.on_event_.enabled_);
61,782✔
342
        counter_data_.increment_on_event_count();
61,782✔
343

344
        std::unique_lock<mutex_type> l(mutex_);
61,782✔
345

346
        bool handled = false;
61,782✔
347
        naming::gid_type new_gid;
61,782✔
348

349
        if (call_for_past_events)
61,782✔
350
        {
351
            gid_table_type::iterator it = gids_.find(name);
61,782✔
352
            if (it != gids_.end())
61,782✔
353
            {
354
                // hold on to entry while map is unlocked
355
                std::shared_ptr<naming::gid_type> current_gid(it->second);
51,666✔
356

357
                // split the credit as the receiving end will expect to keep the
358
                // object alive
359
                {
360
                    unlock_guard<std::unique_lock<mutex_type>> ul(l);
51,666✔
361
                    new_gid =
51,666✔
362
                        naming::detail::split_gid_if_needed(*current_gid).get();
51,666✔
363

364
                    // trigger the lco
365
                    handled = true;
51,666✔
366

367
                    // trigger LCO as name is already bound to an id
368
                    set_lco_value(lco, new_gid);
51,666✔
369

370
                    LAGAS_(info).format(
51,666✔
371
                        "symbol_namespace::on_event, notify: key({1}), "
×
372
                        "stored_gid({2}), new_gid({3})",
373
                        name, *current_gid, new_gid);
×
374
                }
51,666✔
375
            }
51,666✔
376
        }
61,782✔
377

378
        if (!handled)
61,782✔
379
        {
380
            on_event_data_map_type::iterator it = on_event_data_.insert(
10,116✔
381
                on_event_data_map_type::value_type(name, lco));
10,116✔
382

383
            // This overload of insert always returns the iterator pointing
384
            // to the inserted value. It should never point to end
385
            HPX_ASSERT(it != on_event_data_.end());
10,116✔
386
            HPX_UNUSED(it);
10,116✔
387
        }
10,116✔
388
        l.unlock();
61,782✔
389

390
        LAGAS_(info).format("symbol_namespace::on_event: name({1})", name);
61,782✔
391

392
        return true;
393
    }    // }}}
61,782✔
394

395
    // access current counter values
396
    std::int64_t symbol_namespace::counter_data::get_bind_count(bool reset)
×
397
    {
398
        return util::get_and_reset_value(bind_.count_, reset);
×
399
    }
400

401
    std::int64_t symbol_namespace::counter_data::get_resolve_count(bool reset)
×
402
    {
403
        return util::get_and_reset_value(resolve_.count_, reset);
×
404
    }
405

406
    std::int64_t symbol_namespace::counter_data::get_unbind_count(bool reset)
×
407
    {
408
        return util::get_and_reset_value(unbind_.count_, reset);
×
409
    }
410

411
    std::int64_t symbol_namespace::counter_data::get_iterate_names_count(
×
412
        bool reset)
413
    {
414
        return util::get_and_reset_value(iterate_names_.count_, reset);
×
415
    }
416

417
    std::int64_t symbol_namespace::counter_data::get_on_event_count(bool reset)
×
418
    {
419
        return util::get_and_reset_value(on_event_.count_, reset);
×
420
    }
421

422
    std::int64_t symbol_namespace::counter_data::get_overall_count(bool reset)
×
423
    {
424
        return util::get_and_reset_value(bind_.count_, reset) +
×
425
            util::get_and_reset_value(resolve_.count_, reset) +
×
426
            util::get_and_reset_value(unbind_.count_, reset) +
×
427
            util::get_and_reset_value(iterate_names_.count_, reset) +
×
428
            util::get_and_reset_value(on_event_.count_, reset);
×
429
    }
430

431
    void symbol_namespace::counter_data::enable_all()
×
432
    {
433
        bind_.enabled_ = true;
×
434
        resolve_.enabled_ = true;
×
435
        unbind_.enabled_ = true;
×
436
        iterate_names_.enabled_ = true;
×
437
        on_event_.enabled_ = true;
×
438
    }
×
439

440
    // access execution time counters
441
    std::int64_t symbol_namespace::counter_data::get_bind_time(bool reset)
×
442
    {
443
        return util::get_and_reset_value(bind_.time_, reset);
×
444
    }
445

446
    std::int64_t symbol_namespace::counter_data::get_resolve_time(bool reset)
×
447
    {
448
        return util::get_and_reset_value(resolve_.time_, reset);
×
449
    }
450

451
    std::int64_t symbol_namespace::counter_data::get_unbind_time(bool reset)
×
452
    {
453
        return util::get_and_reset_value(unbind_.time_, reset);
×
454
    }
455

456
    std::int64_t symbol_namespace::counter_data::get_iterate_names_time(
×
457
        bool reset)
458
    {
459
        return util::get_and_reset_value(iterate_names_.time_, reset);
×
460
    }
461

462
    std::int64_t symbol_namespace::counter_data::get_on_event_time(bool reset)
×
463
    {
464
        return util::get_and_reset_value(on_event_.time_, reset);
×
465
    }
466

467
    std::int64_t symbol_namespace::counter_data::get_overall_time(bool reset)
×
468
    {
469
        return util::get_and_reset_value(bind_.time_, reset) +
×
470
            util::get_and_reset_value(resolve_.time_, reset) +
×
471
            util::get_and_reset_value(unbind_.time_, reset) +
×
472
            util::get_and_reset_value(iterate_names_.time_, reset) +
×
473
            util::get_and_reset_value(on_event_.time_, reset);
×
474
    }
475

476
    // increment counter values
477
    void symbol_namespace::counter_data::increment_bind_count()
7,659✔
478
    {
479
        if (bind_.enabled_)
7,659✔
480
        {
481
            ++bind_.count_;
×
482
        }
×
483
    }
7,659✔
484

485
    void symbol_namespace::counter_data::increment_resolve_count()
114✔
486
    {
487
        if (resolve_.enabled_)
114✔
488
        {
489
            ++resolve_.count_;
×
490
        }
×
491
    }
114✔
492

493
    void symbol_namespace::counter_data::increment_unbind_count()
3,420✔
494
    {
495
        if (unbind_.enabled_)
3,420✔
496
        {
497
            ++unbind_.count_;
×
498
        }
×
499
    }
3,420✔
500

501
    void symbol_namespace::counter_data::increment_iterate_names_count()
×
502
    {
503
        if (iterate_names_.enabled_)
×
504
        {
505
            ++iterate_names_.count_;
×
506
        }
×
507
    }
×
508

509
    void symbol_namespace::counter_data::increment_on_event_count()
61,782✔
510
    {
511
        if (on_event_.enabled_)
61,782✔
512
        {
513
            ++on_event_.count_;
×
514
        }
×
515
    }
61,782✔
516

517
}}}    // 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