• 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

33.39
/libs/full/performance_counters/src/registry.cpp
1
//  Copyright (c) 2007-2022 Hartmut Kaiser
2
//  Copyright (c)      2011 Bryce Lelbach
3
//
4
//  SPDX-License-Identifier: BSL-1.0
5
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
6
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7

8
#include <hpx/config.hpp>
9
#include <hpx/components_base/agas_interface.hpp>
10
#include <hpx/components_base/server/create_component.hpp>
11
#include <hpx/functional/bind.hpp>
12
#include <hpx/functional/bind_front.hpp>
13
#include <hpx/functional/function.hpp>
14
#include <hpx/modules/logging.hpp>
15
#include <hpx/performance_counters/counters.hpp>
16
#include <hpx/performance_counters/registry.hpp>
17
#include <hpx/performance_counters/server/arithmetics_counter.hpp>
18
#include <hpx/performance_counters/server/arithmetics_counter_extended.hpp>
19
#include <hpx/performance_counters/server/elapsed_time_counter.hpp>
20
#include <hpx/performance_counters/server/raw_counter.hpp>
21
#include <hpx/performance_counters/server/raw_values_counter.hpp>
22
#include <hpx/performance_counters/server/statistics_counter.hpp>
23
#include <hpx/statistics/rolling_max.hpp>
24
#include <hpx/statistics/rolling_min.hpp>
25
#include <hpx/util/regex_from_pattern.hpp>
26

27
#include <boost/accumulators/statistics/rolling_variance.hpp>
28
#include <boost/accumulators/statistics_fwd.hpp>
29

30
#include <cstddef>
31
#include <cstdint>
32
#include <functional>
33
#include <regex>
34
#include <string>
35
#include <utility>
36
#include <vector>
37

38
///////////////////////////////////////////////////////////////////////////////
39
namespace hpx { namespace performance_counters {
40

41
    ///////////////////////////////////////////////////////////////////////////
42
    void registry::clear()
591✔
43
    {
44
        countertypes_.clear();
591✔
45
    }
591✔
46

47
    registry::counter_type_map_type::iterator registry::locate_counter_type(
145,260✔
48
        std::string const& type_name)
49
    {
50
        counter_type_map_type::iterator it = countertypes_.find(type_name);
145,260✔
51
        if (it == countertypes_.end())
145,260✔
52
        {
53
            // if the full type is not available, try to locate the object name
54
            // as a type only
55
            error_code ec(throwmode::lightweight);
72,573✔
56
            counter_path_elements p;
72,573✔
57
            get_counter_type_path_elements(type_name, p, ec);
72,573✔
58
            if (!ec)
72,573✔
59
                it = countertypes_.find("/" + p.objectname_);
72,573✔
60
        }
72,573✔
61
        return it;
145,260✔
62
    }
×
63

64
    registry::counter_type_map_type::const_iterator
65
    registry::locate_counter_type(std::string const& type_name) const
63✔
66
    {
67
        counter_type_map_type::const_iterator it =
68
            countertypes_.find(type_name);
63✔
69
        if (it == countertypes_.end())
63✔
70
        {
71
            // if the full type is not available, try to locate the object name
72
            // as a type only
73
            error_code ec(throwmode::lightweight);
×
74
            counter_path_elements p;
×
75
            get_counter_type_path_elements(type_name, p, ec);
×
76
            if (!ec)
×
77
                it = countertypes_.find("/" + p.objectname_);
×
78
        }
×
79
        return it;
63✔
80
    }
×
81

82
    ///////////////////////////////////////////////////////////////////////////
83
    counter_status registry::add_counter_type(counter_info const& info,
72,573✔
84
        create_counter_func const& create_counter_,
85
        discover_counters_func const& discover_counters_, error_code& ec)
86
    {
87
        // create canonical type name
88
        std::string type_name;
72,573✔
89
        counter_status status =
72,573✔
90
            get_counter_type_name(info.fullname_, type_name, ec);
72,573✔
91
        if (!status_is_valid(status))
72,573✔
92
            return status;
×
93

94
        counter_type_map_type::iterator it = locate_counter_type(type_name);
72,573✔
95
        if (it != countertypes_.end())
72,573✔
96
        {
97
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
98
                "registry::add_counter_type",
99
                "counter type already defined: {}", type_name);
100
            return counter_status::already_defined;
×
101
        }
102

103
        std::pair<counter_type_map_type::iterator, bool> p =
104
            countertypes_.insert(counter_type_map_type::value_type(type_name,
72,573✔
105
                counter_data(info, create_counter_, discover_counters_)));
72,573✔
106

107
        if (!p.second)
72,573✔
108
        {
109
            LPCS_(warning).format(
×
110
                "failed to register counter type {}", type_name);
×
111
            return counter_status::invalid_data;
×
112
        }
113

114
        LPCS_(info).format("counter type {} registered", type_name);
72,573✔
115

116
        if (&ec != &throws)
72,573✔
117
            ec = make_success_code();
×
118
        return counter_status::valid_data;
72,573✔
119
    }
72,573✔
120

121
    /// \brief Call the supplied function for the given registered counter type.
122
    counter_status registry::discover_counter_type(std::string const& fullname,
5✔
123
        discover_counter_func discover_counter, discover_counters_mode mode,
124
        error_code& ec)
125
    {
126
        // create canonical type name
127
        std::string type_name;
5✔
128
        counter_status status = get_counter_type_name(fullname, type_name, ec);
5✔
129
        if (!status_is_valid(status))
5✔
130
            return status;
×
131

132
        if (type_name.find_first_of("*?[]") == std::string::npos)
5✔
133
        {
134
            counter_type_map_type::iterator it = locate_counter_type(type_name);
5✔
135
            if (it == countertypes_.end())
5✔
136
            {
137
                // compose a list of known counter types
138
                std::string types;
×
139
                counter_type_map_type::const_iterator end = countertypes_.end();
×
140
                for (counter_type_map_type::const_iterator it =
×
141
                         countertypes_.begin();
×
142
                     it != end; ++it)
×
143
                {
144
                    types += "  " + (*it).first + "\n";
×
145
                }
×
146

147
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
148
                    "registry::discover_counter_type",
149
                    "unknown counter type: {}, known counter types: \n{}",
150
                    type_name, types);
151
                return counter_status::counter_type_unknown;
×
152
            }
×
153

154
            if (mode == discover_counters_mode::full)
5✔
155
            {
156
                using hpx::placeholders::_1;
157
                discover_counter = hpx::bind(
5✔
158
                    &expand_counter_info, _1, discover_counter, std::ref(ec));
5✔
159
            }
5✔
160

161
            counter_info info = (*it).second.info_;
5✔
162
            info.fullname_ = fullname;
5✔
163

164
            if (!(*it).second.discover_counters_.empty() &&
10✔
165
                !(*it).second.discover_counters_(
10✔
166
                    info, discover_counter, mode, ec))
5✔
167
            {
168
                return counter_status::invalid_data;
×
169
            }
170
        }
5✔
171
        else
172
        {
173
            std::string str_rx(util::regex_from_pattern(type_name, ec));
×
174
            if (ec)
×
175
                return counter_status::invalid_data;
×
176

177
            if (mode == discover_counters_mode::full)
×
178
            {
179
                using hpx::placeholders::_1;
180
                discover_counter = hpx::bind(
×
181
                    &expand_counter_info, _1, discover_counter, std::ref(ec));
×
182
            }
×
183

184
            // split name
185
            counter_path_elements p;
×
186
            get_counter_path_elements(fullname, p, ec);
×
187
            if (ec)
×
188
                return counter_status::invalid_data;
×
189

190
            bool found_one = false;
×
191
            std::regex rx(str_rx);
×
192

193
            counter_type_map_type::const_iterator end = countertypes_.end();
×
194
            for (counter_type_map_type::const_iterator it =
×
195
                     countertypes_.begin();
×
196
                 it != end; ++it)
×
197
            {
198
                if (!std::regex_match((*it).first, rx))
×
199
                    continue;
×
200
                found_one = true;
×
201

202
                // propagate parameters
203
                counter_info info = (*it).second.info_;
×
204
                if (!p.parameters_.empty())
×
205
                    info.fullname_ += "@" + p.parameters_;
×
206

207
                if (!(*it).second.discover_counters_.empty() &&
×
208
                    !(*it).second.discover_counters_(
×
209
                        info, discover_counter, mode, ec))
×
210
                {
211
                    return counter_status::invalid_data;
×
212
                }
213
            }
×
214

215
            if (!found_one)
×
216
            {
217
                // compose a list of known counter types
218
                std::string types;
×
219
                counter_type_map_type::const_iterator end = countertypes_.end();
×
220
                for (counter_type_map_type::const_iterator it =
×
221
                         countertypes_.begin();
×
222
                     it != end; ++it)
×
223
                {
224
                    types += "  " + (*it).first + "\n";
×
225
                }
×
226

227
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
228
                    "registry::discover_counter_type",
229
                    "counter type {} does not match any known type, known "
230
                    "counter types: \n{}",
231
                    type_name, types);
232
                return counter_status::counter_type_unknown;
×
233
            }
×
234
        }
×
235

236
        if (&ec != &throws)
5✔
237
            ec = make_success_code();
×
238

239
        return counter_status::valid_data;
5✔
240
    }
5✔
241

242
    /// \brief Call the supplied function for all registered counter types.
243
    counter_status registry::discover_counter_types(
1✔
244
        discover_counter_func discover_counter, discover_counters_mode mode,
245
        error_code& ec)
246
    {
247
        // Introducing this temporary silence a report about a potential memory
248
        // from clang's static analyzer
249
        discover_counter_func discover_counter_;
1✔
250
        if (mode == discover_counters_mode::full)
1✔
251
        {
252
            using hpx::placeholders::_1;
253
            discover_counter_ = hpx::bind(&expand_counter_info, _1,
×
254
                HPX_MOVE(discover_counter), std::ref(ec));
×
255
        }
×
256
        else
257
        {
258
            discover_counter_ = HPX_MOVE(discover_counter);
1✔
259
        }
260

261
        for (counter_type_map_type::value_type const& d : countertypes_)
128✔
262
        {
263
            if (!d.second.discover_counters_.empty() &&
254✔
264
                !d.second.discover_counters_(
254✔
265
                    d.second.info_, discover_counter_, mode, ec))
127✔
266
            {
267
                return counter_status::invalid_data;
×
268
            }
269
        }
270

271
        if (&ec != &throws)
1✔
272
            ec = make_success_code();
×
273

274
        return counter_status::valid_data;
1✔
275
    }
1✔
276

277
    ///////////////////////////////////////////////////////////////////////////
278
    counter_status registry::get_counter_create_function(
63✔
279
        counter_info const& info, create_counter_func& func,
280
        error_code& ec) const
281
    {
282
        // create canonical type name
283
        std::string type_name;
63✔
284
        counter_status status =
63✔
285
            get_counter_type_name(info.fullname_, type_name, ec);
63✔
286
        if (!status_is_valid(status))
63✔
287
            return status;
×
288

289
        counter_type_map_type::const_iterator it =
290
            locate_counter_type(type_name);
63✔
291
        if (it == countertypes_.end())
63✔
292
        {
293
            // compose a list of known counter types
294
            std::string types;
×
295
            counter_type_map_type::const_iterator end = countertypes_.end();
×
296
            for (counter_type_map_type::const_iterator it =
×
297
                     countertypes_.begin();
×
298
                 it != end; ++it)
×
299
            {
300
                types += "  " + (*it).first + "\n";
×
301
            }
×
302

303
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
304
                "registry::get_counter_create_function",
305
                "counter type {} is not defined, known counter types: \n{}",
306
                type_name, types);
307
            return counter_status::counter_type_unknown;
×
308
        }
×
309

310
        if ((*it).second.create_counter_.empty())
63✔
311
        {
312
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
313
                "registry::get_counter_create_function",
314
                "counter type {} has no associated create function", type_name);
315
            return counter_status::invalid_data;
×
316
        }
317

318
        func = (*it).second.create_counter_;
63✔
319

320
        if (&ec != &throws)
63✔
321
            ec = make_success_code();
63✔
322
        return counter_status::valid_data;
63✔
323
    }
63✔
324

325
    ///////////////////////////////////////////////////////////////////////////
326
    counter_status registry::get_counter_discovery_function(
×
327
        counter_info const& info, discover_counters_func& func,
328
        error_code& ec) const
329
    {
330
        // create canonical type name
331
        std::string type_name;
×
332
        counter_status status =
×
333
            get_counter_type_name(info.fullname_, type_name, ec);
×
334
        if (!status_is_valid(status))
×
335
            return status;
×
336

337
        counter_type_map_type::const_iterator it =
338
            locate_counter_type(type_name);
×
339
        if (it == countertypes_.end())
×
340
        {
341
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
342
                "registry::get_counter_discovery_function",
343
                "counter type {} is not defined", type_name);
344
            return counter_status::counter_type_unknown;
×
345
        }
346

347
        if ((*it).second.discover_counters_.empty())
×
348
        {
349
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
350
                "registry::get_counter_discovery_function",
351
                "counter type {} has no associated discovery function",
352
                type_name);
353
            return counter_status::invalid_data;
×
354
        }
355

356
        func = (*it).second.discover_counters_;
×
357

358
        if (&ec != &throws)
×
359
            ec = make_success_code();
×
360
        return counter_status::valid_data;
×
361
    }
×
362

363
    ///////////////////////////////////////////////////////////////////////////
364
    counter_status registry::remove_counter_type(
72,469✔
365
        counter_info const& info, error_code& ec)
366
    {
367
        // create canonical type name
368
        std::string type_name;
72,469✔
369
        counter_status status =
72,469✔
370
            get_counter_type_name(info.fullname_, type_name, ec);
72,469✔
371
        if (!status_is_valid(status))
72,469✔
372
            return status;
×
373

374
        counter_type_map_type::iterator it = locate_counter_type(type_name);
72,469✔
375
        if (it == countertypes_.end())
72,469✔
376
        {
377
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
378
                "registry::remove_counter_type", "counter type is not defined");
379
            return counter_status::counter_type_unknown;
×
380
        }
381

382
        LPCS_(info).format("counter type {} unregistered", type_name);
72,469✔
383

384
        countertypes_.erase(it);
72,469✔
385

386
        if (&ec != &throws)
72,469✔
387
            ec = make_success_code();
72,469✔
388
        return counter_status::valid_data;
72,469✔
389
    }
72,469✔
390

391
    ///////////////////////////////////////////////////////////////////////////
392
    std::int64_t wrap_counter(std::int64_t* p, bool /* reset */)
×
393
    {
394
        std::int64_t result = *p;
×
395
        *p = 0;
×
396
        return result;
×
397
    }
398

399
    ///////////////////////////////////////////////////////////////////////////
400
    counter_status registry::create_raw_counter_value(counter_info const& info,
×
401
        std::int64_t* countervalue, naming::gid_type& id, error_code& ec)
402
    {
403
        hpx::function<std::int64_t(bool)> func(
×
404
            hpx::bind_front(wrap_counter, countervalue));
×
405
        return create_raw_counter(info, func, id, ec);
×
406
    }
×
407

408
    static std::int64_t wrap_raw_counter(
11✔
409
        hpx::function<std::int64_t()> const& f, bool)
410
    {
411
        return f();
11✔
412
    }
413

414
    static std::vector<std::int64_t> wrap_raw_values_counter(
×
415
        hpx::function<std::vector<std::int64_t>()> const& f, bool)
416
    {
417
        return f();
×
418
    }
419

420
    counter_status registry::create_raw_counter(counter_info const& info,
3✔
421
        hpx::function<std::int64_t()> const& f, naming::gid_type& id,
422
        error_code& ec)
423
    {
424
        hpx::function<std::int64_t(bool)> func(
3✔
425
            hpx::bind_front(&wrap_raw_counter, f));
3✔
426
        return create_raw_counter(info, func, id, ec);
3✔
427
    }
3✔
428

429
    counter_status registry::create_raw_counter(counter_info const& info,
58✔
430
        hpx::function<std::int64_t(bool)> const& f, naming::gid_type& id,
431
        error_code& ec)
432
    {
433
        // create canonical type name
434
        std::string type_name;
58✔
435
        counter_status status =
58✔
436
            get_counter_type_name(info.fullname_, type_name, ec);
58✔
437
        if (!status_is_valid(status))
58✔
438
            return status;
×
439

440
        counter_type_map_type::iterator it = locate_counter_type(type_name);
58✔
441
        if (it == countertypes_.end())
58✔
442
        {
443
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
444
                "registry::create_raw_counter", "unknown counter type {}",
445
                type_name);
446
            return counter_status::counter_type_unknown;
×
447
        }
448

449
        // make sure the counter type requested is supported
450
        if ((counter_type::raw != (*it).second.info_.type_ ||
58✔
451
                counter_type::raw != info.type_) &&
34✔
452
            (counter_type::monotonically_increasing !=
24✔
453
                    (*it).second.info_.type_ ||
48✔
454
                counter_type::monotonically_increasing != info.type_) &&
20✔
455
            (counter_type::aggregating != (*it).second.info_.type_ ||
4✔
456
                counter_type::aggregating != info.type_) &&
×
457
            (counter_type::elapsed_time != (*it).second.info_.type_ ||
4✔
458
                counter_type::elapsed_time != info.type_) &&
4✔
459
            (counter_type::average_count != (*it).second.info_.type_ ||
×
460
                counter_type::average_count != info.type_) &&
×
461
            (counter_type::average_timer != (*it).second.info_.type_ ||
×
462
                counter_type::average_timer != info.type_))
×
463
        {
464
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
465
                "registry::create_raw_counter",
466
                "invalid counter type requested (only counter_type::raw, "
467
                "counter_type::monotonically_increasing, "
468
                "counter_type::aggregating, "
469
                "counter_type::elapsed_time, counter_type::average_count, or "
470
                "counter_type::average_timer are supported)");
471
            return counter_status::counter_type_unknown;
×
472
        }
473

474
        // make sure parent instance name is set properly
475
        counter_info complemented_info = info;
58✔
476
        complement_counter_info(complemented_info, (*it).second.info_, ec);
58✔
477
        if (ec)
58✔
478
            return counter_status::invalid_data;
×
479

480
        // create the counter as requested
481
        try
482
        {
483
            typedef components::component<server::raw_counter> counter_t;
484
            id = components::server::construct<counter_t>(complemented_info, f);
58✔
485
        }
58✔
486
        catch (hpx::exception const& e)
487
        {
488
            id = naming::invalid_gid;    // reset result
×
489
            if (&ec == &throws)
×
490
                throw;
×
491
            ec = make_error_code(e.get_error(), e.what());
×
492
            LPCS_(warning).format("failed to create raw counter {} ({})",
×
493
                complemented_info.fullname_, e.what());
×
494
            return counter_status::invalid_data;
×
495
        }
×
496

497
        LPCS_(info).format(
58✔
498
            "raw counter {} created at {}", complemented_info.fullname_, id);
58✔
499

500
        if (&ec != &throws)
58✔
501
            ec = make_success_code();
58✔
502
        return counter_status::valid_data;
58✔
503
    }
58✔
504

505
    counter_status registry::create_raw_counter(counter_info const& info,
×
506
        hpx::function<std::vector<std::int64_t>()> const& f,
507
        naming::gid_type& id, error_code& ec)
508
    {
509
        hpx::function<std::vector<std::int64_t>(bool)> func(
×
510
            hpx::bind_front(&wrap_raw_values_counter, f));
×
511
        return create_raw_counter(info, func, id, ec);
×
512
    }
×
513

514
    counter_status registry::create_raw_counter(counter_info const& info,
1✔
515
        hpx::function<std::vector<std::int64_t>(bool)> const& f,
516
        naming::gid_type& id, error_code& ec)
517
    {
518
        // create canonical type name
519
        std::string type_name;
1✔
520
        counter_status status =
1✔
521
            get_counter_type_name(info.fullname_, type_name, ec);
1✔
522
        if (!status_is_valid(status))
1✔
523
            return status;
×
524

525
        counter_type_map_type::iterator it = locate_counter_type(type_name);
1✔
526
        if (it == countertypes_.end())
1✔
527
        {
528
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
529
                "registry::create_raw_counter", "unknown counter type {}",
530
                type_name);
531
            return counter_status::counter_type_unknown;
×
532
        }
533

534
        // make sure the counter type requested is supported
535
        if (!((counter_type::histogram == (*it).second.info_.type_ &&
2✔
536
                  counter_type::histogram == info.type_) ||
×
537
                (counter_type::raw_values == (*it).second.info_.type_ &&
1✔
538
                    counter_type::raw_values == info.type_)))
1✔
539
        {
540
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
541
                "registry::create_raw_counter",
542
                "invalid counter type requested (only counter_histogram or "
543
                "counter_raw_values are supported)");
544
            return counter_status::counter_type_unknown;
×
545
        }
546

547
        // make sure parent instance name is set properly
548
        counter_info complemented_info = info;
1✔
549
        complement_counter_info(complemented_info, (*it).second.info_, ec);
1✔
550
        if (ec)
1✔
551
            return counter_status::invalid_data;
×
552

553
        // create the counter as requested
554
        try
555
        {
556
            typedef components::component<server::raw_values_counter> counter_t;
557
            id = components::server::construct<counter_t>(complemented_info, f);
1✔
558
        }
1✔
559
        catch (hpx::exception const& e)
560
        {
561
            id = naming::invalid_gid;    // reset result
×
562
            if (&ec == &throws)
×
563
                throw;
×
564
            ec = make_error_code(e.get_error(), e.what());
×
565
            LPCS_(warning).format("failed to create raw counter {} ({})",
×
566
                complemented_info.fullname_, e.what());
×
567
            return counter_status::invalid_data;
×
568
        }
×
569

570
        LPCS_(info).format(
1✔
571
            "raw counter {} created at {}", complemented_info.fullname_, id);
1✔
572

573
        if (&ec != &throws)
1✔
574
            ec = make_success_code();
1✔
575
        return counter_status::valid_data;
1✔
576
    }
1✔
577

578
    ///////////////////////////////////////////////////////////////////////////
579
    counter_status registry::create_counter(
2✔
580
        counter_info const& info, naming::gid_type& id, error_code& ec)
581
    {
582
        // create canonical type name
583
        std::string type_name;
2✔
584
        counter_status status =
2✔
585
            get_counter_type_name(info.fullname_, type_name, ec);
2✔
586
        if (!status_is_valid(status))
2✔
587
            return status;
×
588

589
        counter_type_map_type::iterator it = locate_counter_type(type_name);
2✔
590
        if (it == countertypes_.end())
2✔
591
        {
592
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
593
                "registry::create_counter", "unknown counter type {}",
594
                type_name);
595
            return counter_status::counter_type_unknown;
×
596
        }
597

598
        // make sure parent instance name is set properly
599
        counter_info complemented_info = info;
2✔
600
        complement_counter_info(complemented_info, (*it).second.info_, ec);
2✔
601
        if (ec)
2✔
602
            return counter_status::invalid_data;
×
603

604
        // create the counter as requested
605
        try
606
        {
607
            switch (complemented_info.type_)
2✔
608
            {
609
            case counter_type::elapsed_time:
610
            {
611
                typedef components::component<server::elapsed_time_counter>
612
                    counter_t;
613
                id =
2✔
614
                    components::server::construct<counter_t>(complemented_info);
2✔
615
            }
616
            break;
2✔
617

618
            // NOLINTNEXTLINE(bugprone-branch-clone)
619
            case counter_type::raw:
620
                [[fallthrough]];
621
            case counter_type::monotonically_increasing:
622
                [[fallthrough]];
623
            case counter_type::aggregating:
624
                [[fallthrough]];
625
            case counter_type::average_count:
626
                [[fallthrough]];
627
            case counter_type::average_timer:
628
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
629
                    "registry::create_counter",
630
                    "need function parameter for raw_counter");
631
                return counter_status::counter_type_unknown;
×
632

633
            default:
634
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
635
                    "registry::create_counter",
636
                    "invalid counter type requested");
637
                return counter_status::counter_type_unknown;
×
638
            }
639
        }
2✔
640
        catch (hpx::exception const& e)
641
        {
642
            id = naming::invalid_gid;    // reset result
×
643
            if (&ec == &throws)
×
644
                throw;
×
645
            ec = make_error_code(e.get_error(), e.what());
×
646
            LPCS_(warning).format("failed to create counter {} ({})",
×
647
                complemented_info.fullname_, e.what());
×
648
            return counter_status::invalid_data;
×
649
        }
×
650

651
        LPCS_(info).format(
2✔
652
            "counter {} created at {}", complemented_info.fullname_, id);
2✔
653

654
        if (&ec != &throws)
2✔
655
            ec = make_success_code();
2✔
656
        return counter_status::valid_data;
2✔
657
    }
2✔
658

659
    /// \brief Create a new statistics performance counter instance based
660
    ///        on given base counter name and given base time interval
661
    ///        (milliseconds).
662
    counter_status registry::create_statistics_counter(counter_info const& info,
1✔
663
        std::string const& base_counter_name,
664
        std::vector<std::size_t> const& parameters, naming::gid_type& gid,
665
        error_code& ec)
666
    {
667
        // create canonical type name
668
        std::string type_name;
1✔
669
        counter_status status =
1✔
670
            get_counter_type_name(info.fullname_, type_name, ec);
1✔
671
        if (!status_is_valid(status))
1✔
672
            return status;
×
673

674
        counter_type_map_type::iterator it = locate_counter_type(type_name);
1✔
675
        if (it == countertypes_.end())
1✔
676
        {
677
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
678
                "registry::create_statistics_counter",
679
                "unknown counter type {}", type_name);
680
            return counter_status::counter_type_unknown;
×
681
        }
682

683
        // make sure the requested counter type is supported
684
        if (counter_type::aggregating != (*it).second.info_.type_ ||
1✔
685
            counter_type::aggregating != info.type_)
1✔
686
        {
687
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
688
                "registry::create_statistics_counter",
689
                "invalid counter type requested (only "
690
                "counter_type::aggregating is "
691
                "supported)");
692
            return counter_status::counter_type_unknown;
×
693
        }
694

695
        // make sure parent instance name is set properly
696
        counter_info complemented_info = info;
1✔
697
        complement_counter_info(complemented_info, (*it).second.info_, ec);
1✔
698
        if (ec)
1✔
699
            return counter_status::invalid_data;
×
700

701
        // split name
702
        counter_path_elements p;
1✔
703
        get_counter_path_elements(complemented_info.fullname_, p, ec);
1✔
704
        if (ec)
1✔
705
            return counter_status::invalid_data;
×
706

707
        // create the counter as requested
708
        try
709
        {
710
            // extract parameters
711
            std::size_t sample_interval = 1000;    // default sampling interval
1✔
712
            bool reset_base_counter = false;
1✔
713

714
            if (!parameters.empty())
1✔
715
                sample_interval = parameters[0];
1✔
716

717
            // create base counter only if it does not exist yet
718
            if (p.countername_ == "average")
1✔
719
            {
720
                typedef hpx::components::component<
721
                    hpx::performance_counters::server::statistics_counter<
722
                        boost::accumulators::tag::mean>>
723
                    counter_t;
724

725
                if (parameters.size() > 1)
1✔
726
                    reset_base_counter = (parameters[1] != 0) ? true : false;
×
727

728
                gid = components::server::construct<counter_t>(
1✔
729
                    complemented_info, base_counter_name, sample_interval, 0,
1✔
730
                    reset_base_counter);
731
            }
1✔
732
            else if (p.countername_ == "stddev")
×
733
            {
734
                typedef hpx::components::component<
735
                    hpx::performance_counters::server::statistics_counter<
736
                        boost::accumulators::tag::variance>>
737
                    counter_t;
738

739
                if (parameters.size() > 1)
×
740
                    reset_base_counter = (parameters[1] != 0) ? true : false;
×
741

742
                gid = components::server::construct<counter_t>(
×
743
                    complemented_info, base_counter_name, sample_interval, 0,
×
744
                    reset_base_counter);
745
            }
×
746
            else if (p.countername_ == "rolling_average")
×
747
            {
748
                typedef hpx::components::component<
749
                    hpx::performance_counters::server::statistics_counter<
750
                        boost::accumulators::tag::rolling_mean>>
751
                    counter_t;
752

753
                std::size_t window_size = 10;    // default rolling window size
×
754
                if (parameters.size() > 1)
×
755
                    window_size = parameters[1];
×
756

757
                if (parameters.size() > 2)
×
758
                    reset_base_counter = (parameters[2] != 0) ? true : false;
×
759

760
                gid = components::server::construct<counter_t>(
×
761
                    complemented_info, base_counter_name, sample_interval,
×
762
                    window_size, reset_base_counter);
763
            }
×
764
            else if (p.countername_ == "rolling_stddev")
×
765
            {
766
                typedef hpx::components::component<
767
                    hpx::performance_counters::server::statistics_counter<
768
                        boost::accumulators::tag::rolling_variance>>
769
                    counter_t;
770

771
                std::size_t window_size = 10;    // default rolling window size
×
772
                if (parameters.size() > 1)
×
773
                    window_size = parameters[1];
×
774

775
                if (parameters.size() > 2)
×
776
                    reset_base_counter = (parameters[2] != 0) ? true : false;
×
777

778
                gid = components::server::construct<counter_t>(
×
779
                    complemented_info, base_counter_name, sample_interval,
×
780
                    window_size, reset_base_counter);
781
            }
×
782
            else if (p.countername_ == "median")
×
783
            {
784
                typedef hpx::components::component<
785
                    hpx::performance_counters::server::statistics_counter<
786
                        boost::accumulators::tag::median>>
787
                    counter_t;
788

789
                if (parameters.size() > 1)
×
790
                    reset_base_counter = (parameters[1] != 0) ? true : false;
×
791

792
                gid = components::server::construct<counter_t>(
×
793
                    complemented_info, base_counter_name, sample_interval, 0,
×
794
                    reset_base_counter);
795
            }
×
796
            else if (p.countername_ == "max")
×
797
            {
798
                typedef hpx::components::component<
799
                    hpx::performance_counters::server::statistics_counter<
800
                        boost::accumulators::tag::max>>
801
                    counter_t;
802

803
                if (parameters.size() > 1)
×
804
                    reset_base_counter = (parameters[1] != 0) ? true : false;
×
805

806
                gid = components::server::construct<counter_t>(
×
807
                    complemented_info, base_counter_name, sample_interval, 0,
×
808
                    reset_base_counter);
809
            }
×
810
            else if (p.countername_ == "min")
×
811
            {
812
                typedef hpx::components::component<
813
                    hpx::performance_counters::server::statistics_counter<
814
                        boost::accumulators::tag::min>>
815
                    counter_t;
816

817
                if (parameters.size() > 1)
×
818
                    reset_base_counter = (parameters[1] != 0) ? true : false;
×
819

820
                gid = components::server::construct<counter_t>(
×
821
                    complemented_info, base_counter_name, sample_interval, 0,
×
822
                    reset_base_counter);
823
            }
×
824
            else if (p.countername_ == "rolling_min")
×
825
            {
826
                typedef hpx::components::component<hpx::performance_counters::
827
                        server::statistics_counter<hpx::util::tag::rolling_min>>
828
                    counter_t;
829

830
                std::size_t window_size = 10;    // default rolling window size
×
831
                if (parameters.size() > 1)
×
832
                    window_size = parameters[1];
×
833

834
                if (parameters.size() > 2)
×
835
                    reset_base_counter = (parameters[2] != 0) ? true : false;
×
836

837
                gid = components::server::construct<counter_t>(
×
838
                    complemented_info, base_counter_name, sample_interval,
×
839
                    window_size, reset_base_counter);
840
            }
×
841
            else if (p.countername_ == "rolling_max")
×
842
            {
843
                typedef hpx::components::component<hpx::performance_counters::
844
                        server::statistics_counter<hpx::util::tag::rolling_max>>
845
                    counter_t;
846

847
                std::size_t window_size = 10;    // default rolling window size
×
848
                if (parameters.size() > 1)
×
849
                    window_size = parameters[1];
×
850

851
                if (parameters.size() > 2)
×
852
                    reset_base_counter = (parameters[2] != 0) ? true : false;
×
853

854
                gid = components::server::construct<counter_t>(
×
855
                    complemented_info, base_counter_name, sample_interval,
×
856
                    window_size, reset_base_counter);
857
            }
×
858
            else
859
            {
860
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
861
                    "registry::create_statistics_counter",
862
                    "invalid counter type requested: {}", p.countername_);
863
                return counter_status::counter_type_unknown;
×
864
            }
865
        }
1✔
866
        catch (hpx::exception const& e)
867
        {
868
            gid = naming::invalid_gid;    // reset result
×
869
            if (&ec == &throws)
×
870
                throw;
×
871

872
            ec = make_error_code(e.get_error(), e.what());
×
873
            LPCS_(warning).format("failed to create statistics counter {} ({})",
×
874
                complemented_info.fullname_, e.what());
×
875
            return counter_status::invalid_data;
×
876
        }
×
877

878
        LPCS_(info).format("statistics counter {} created at {}",
1✔
879
            complemented_info.fullname_, gid);
1✔
880

881
        if (&ec != &throws)
1✔
882
            ec = make_success_code();
1✔
883
        return counter_status::valid_data;
1✔
884
    }
1✔
885

886
    /// \brief Create a new arithmetics performance counter instance based
887
    ///        on given base counter names
888
    counter_status registry::create_arithmetics_counter(
×
889
        counter_info const& info,
890
        std::vector<std::string> const& base_counter_names,
891
        naming::gid_type& gid, error_code& ec)
892
    {
893
        // create canonical type name
894
        std::string type_name;
×
895
        counter_status status =
×
896
            get_counter_type_name(info.fullname_, type_name, ec);
×
897
        if (!status_is_valid(status))
×
898
            return status;
×
899

900
        counter_type_map_type::iterator it = locate_counter_type(type_name);
×
901
        if (it == countertypes_.end())
×
902
        {
903
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
904
                "registry::create_arithmetics_counter",
905
                "unknown counter type {}", type_name);
906
            return counter_status::counter_type_unknown;
×
907
        }
908

909
        // make sure the requested counter type is supported
910
        if (counter_type::aggregating != (*it).second.info_.type_ ||
×
911
            counter_type::aggregating != info.type_)
×
912
        {
913
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
914
                "registry::create_arithmetics_counter",
915
                "invalid counter type requested "
916
                "(only counter_type::aggregating is supported)");
917
            return counter_status::counter_type_unknown;
×
918
        }
919

920
        // make sure parent instance name is set properly
921
        counter_info complemented_info = info;
×
922
        complement_counter_info(complemented_info, (*it).second.info_, ec);
×
923
        if (ec)
×
924
            return counter_status::invalid_data;
×
925

926
        // split name
927
        counter_path_elements p;
×
928
        get_counter_path_elements(complemented_info.fullname_, p, ec);
×
929
        if (ec)
×
930
            return counter_status::invalid_data;
×
931

932
        // create the counter as requested
933
        try
934
        {
935
            // create base counter only if it does not exist yet
936
            if (p.countername_ == "add")
×
937
            {
938
                typedef hpx::components::component<hpx::performance_counters::
939
                        server::arithmetics_counter<std::plus<double>>>
940
                    counter_t;
941
                gid = components::server::construct<counter_t>(
×
942
                    complemented_info, base_counter_names);
×
943
            }
×
944
            else if (p.countername_ == "subtract")
×
945
            {
946
                typedef hpx::components::component<hpx::performance_counters::
947
                        server::arithmetics_counter<std::minus<double>>>
948
                    counter_t;
949
                gid = components::server::construct<counter_t>(
×
950
                    complemented_info, base_counter_names);
×
951
            }
×
952
            else if (p.countername_ == "multiply")
×
953
            {
954
                typedef hpx::components::component<hpx::performance_counters::
955
                        server::arithmetics_counter<std::multiplies<double>>>
956
                    counter_t;
957
                gid = components::server::construct<counter_t>(
×
958
                    complemented_info, base_counter_names);
×
959
            }
×
960
            else if (p.countername_ == "divide")
×
961
            {
962
                typedef hpx::components::component<hpx::performance_counters::
963
                        server::arithmetics_counter<std::divides<double>>>
964
                    counter_t;
965
                gid = components::server::construct<counter_t>(
×
966
                    complemented_info, base_counter_names);
×
967
            }
×
968
            else
969
            {
970
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
971
                    "registry::create_arithmetics_counter",
972
                    "invalid counter type requested: {}", p.countername_);
973
                return counter_status::counter_type_unknown;
×
974
            }
975
        }
×
976
        catch (hpx::exception const& e)
977
        {
978
            gid = naming::invalid_gid;    // reset result
×
979
            if (&ec == &throws)
×
980
                throw;
×
981

982
            ec = make_error_code(e.get_error(), e.what());
×
983
            LPCS_(warning).format(
×
984
                "failed to create aggregating counter {} ({})",
×
985
                complemented_info.fullname_, e.what());
×
986
            return counter_status::invalid_data;
×
987
        }
×
988

989
        LPCS_(info).format("aggregating counter {} created at {}",
×
990
            complemented_info.fullname_, gid);
×
991

992
        if (&ec != &throws)
×
993
            ec = make_success_code();
×
994
        return counter_status::valid_data;
×
995
    }
×
996

997
    /// \brief Create a new arithmetics extended performance counter instance
998
    ///        based on given base counter names
999
    counter_status registry::create_arithmetics_counter_extended(
×
1000
        counter_info const& info,
1001
        std::vector<std::string> const& base_counter_names,
1002
        naming::gid_type& gid, error_code& ec)
1003
    {
1004
        // create canonical type name
1005
        std::string type_name;
×
1006
        counter_status status =
×
1007
            get_counter_type_name(info.fullname_, type_name, ec);
×
1008
        if (!status_is_valid(status))
×
1009
            return status;
×
1010

1011
        counter_type_map_type::iterator it = locate_counter_type(type_name);
×
1012
        if (it == countertypes_.end())
×
1013
        {
1014
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
1015
                "registry::create_arithmetics_counter_extended",
1016
                "unknown counter type {}", type_name);
1017
            return counter_status::counter_type_unknown;
×
1018
        }
1019

1020
        // make sure the requested counter type is supported
1021
        if (counter_type::aggregating != (*it).second.info_.type_ ||
×
1022
            counter_type::aggregating != info.type_)
×
1023
        {
1024
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
1025
                "registry::create_arithmetics_counter_extended",
1026
                "invalid counter type requested "
1027
                "(only counter_type::aggregating is supported)");
1028
            return counter_status::counter_type_unknown;
×
1029
        }
1030

1031
        // make sure parent instance name is set properly
1032
        counter_info complemented_info = info;
×
1033
        complement_counter_info(complemented_info, (*it).second.info_, ec);
×
1034
        if (ec)
×
1035
            return counter_status::invalid_data;
×
1036

1037
        // split name
1038
        counter_path_elements p;
×
1039
        get_counter_path_elements(complemented_info.fullname_, p, ec);
×
1040
        if (ec)
×
1041
            return counter_status::invalid_data;
×
1042

1043
        // create the counter as requested
1044
        try
1045
        {
1046
            // create base counter only if it does not exist yet
1047
            if (p.countername_ == "mean")
×
1048
            {
1049
                typedef hpx::components::component<hpx::performance_counters::
1050
                        server::arithmetics_counter_extended<
1051
                            boost::accumulators::tag::mean>>
1052
                    counter_t;
1053
                gid = components::server::construct<counter_t>(
×
1054
                    complemented_info, base_counter_names);
×
1055
            }
×
1056
            else if (p.countername_ == "variance")
×
1057
            {
1058
                typedef hpx::components::component<
1059
                    performance_counters::server::arithmetics_counter_extended<
1060
                        boost::accumulators::tag::variance>>
1061
                    counter_t;
1062
                gid = components::server::construct<counter_t>(
×
1063
                    complemented_info, base_counter_names);
×
1064
            }
×
1065
            else if (p.countername_ == "median")
×
1066
            {
1067
                typedef hpx::components::component<
1068
                    performance_counters::server::arithmetics_counter_extended<
1069
                        boost::accumulators::tag::median>>
1070
                    counter_t;
1071
                gid = components::server::construct<counter_t>(
×
1072
                    complemented_info, base_counter_names);
×
1073
            }
×
1074
            else if (p.countername_ == "min")
×
1075
            {
1076
                typedef hpx::components::component<
1077
                    performance_counters::server::arithmetics_counter_extended<
1078
                        boost::accumulators::tag::min>>
1079
                    counter_t;
1080
                gid = components::server::construct<counter_t>(
×
1081
                    complemented_info, base_counter_names);
×
1082
            }
×
1083
            else if (p.countername_ == "max")
×
1084
            {
1085
                typedef hpx::components::component<
1086
                    performance_counters::server::arithmetics_counter_extended<
1087
                        boost::accumulators::tag::max>>
1088
                    counter_t;
1089
                gid = components::server::construct<counter_t>(
×
1090
                    complemented_info, base_counter_names);
×
1091
            }
×
1092
            else if (p.countername_ == "count")
×
1093
            {
1094
                typedef hpx::components::component<
1095
                    performance_counters::server::arithmetics_counter_extended<
1096
                        boost::accumulators::tag::count>>
1097
                    counter_t;
1098
                gid = components::server::construct<counter_t>(
×
1099
                    complemented_info, base_counter_names);
×
1100
            }
×
1101
            else
1102
            {
1103
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
1104
                    "registry::create_arithmetics_counter",
1105
                    "invalid counter type requested: {}", p.countername_);
1106
                return counter_status::counter_type_unknown;
×
1107
            }
1108
        }
×
1109
        catch (hpx::exception const& e)
1110
        {
1111
            gid = naming::invalid_gid;    // reset result
×
1112
            if (&ec == &throws)
×
1113
                throw;
×
1114

1115
            ec = make_error_code(e.get_error(), e.what());
×
1116
            LPCS_(warning).format(
×
1117
                "failed to create aggregating counter {} ({})",
×
1118
                complemented_info.fullname_, e.what());
×
1119
            return counter_status::invalid_data;
×
1120
        }
×
1121

1122
        LPCS_(info).format("aggregating counter {} created at {}",
×
1123
            complemented_info.fullname_, gid);
×
1124

1125
        if (&ec != &throws)
×
1126
            ec = make_success_code();
×
1127
        return counter_status::valid_data;
×
1128
    }
×
1129

1130
    ///////////////////////////////////////////////////////////////////////////
1131
    /// \brief Add an existing performance counter instance to the registry
1132
    counter_status registry::add_counter(
×
1133
        hpx::id_type const& id, counter_info const& info, error_code& ec)
1134
    {
1135
        // complement counter info data
1136
        counter_info complemented_info = info;
×
1137
        complement_counter_info(complemented_info, ec);
×
1138
        if (ec)
×
1139
            return counter_status::invalid_data;
×
1140

1141
        // create canonical type name
1142
        std::string type_name;
×
1143
        counter_status status =
×
1144
            get_counter_type_name(complemented_info.fullname_, type_name, ec);
×
1145
        if (!status_is_valid(status))
×
1146
            return status;
×
1147

1148
        // make sure the type of the new counter is known to the registry
1149
        counter_type_map_type::iterator it = locate_counter_type(type_name);
×
1150
        if (it == countertypes_.end())
×
1151
        {
1152
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
1153
                "registry::add_counter", "unknown counter type {}", type_name);
1154
            return counter_status::counter_type_unknown;
×
1155
        }
1156

1157
        // register the canonical name with AGAS
1158
        std::string name(complemented_info.fullname_);
×
1159
        ensure_counter_prefix(name);    // pre-pend prefix, if necessary
×
1160
        agas::register_name(launch::sync, name, id, ec);
×
1161
        if (ec)
×
1162
            return counter_status::invalid_data;
×
1163

1164
        if (&ec != &throws)
×
1165
            ec = make_success_code();
×
1166
        return counter_status::valid_data;
×
1167
    }
×
1168

1169
    ///////////////////////////////////////////////////////////////////////////
1170
    counter_status registry::remove_counter(
×
1171
        counter_info const& info, hpx::id_type const& /* id */, error_code& ec)
1172
    {
1173
        // make sure parent instance name is set properly
1174
        counter_info complemented_info = info;
×
1175
        complement_counter_info(complemented_info, ec);
×
1176
        if (ec)
×
1177
            return counter_status::invalid_data;
×
1178

1179
        // create canonical name for the counter
1180
        std::string name;
×
1181
        counter_status status =
×
1182
            get_counter_name(complemented_info.fullname_, name, ec);
×
1183
        if (!status_is_valid(status))
×
1184
            return status;
×
1185

1186
        // unregister this counter from AGAS
1187
        ensure_counter_prefix(name);    // pre-pend prefix, if necessary
×
1188
        agas::unregister_name(launch::sync, name, ec);
×
1189
        if (ec)
×
1190
        {
1191
            LPCS_(warning).format(
×
1192
                "failed to remove counter {}", complemented_info.fullname_);
×
1193
            return counter_status::invalid_data;
×
1194
        }
1195

1196
        return counter_status::valid_data;
×
1197
    }
×
1198

1199
    ///////////////////////////////////////////////////////////////////////////
1200
    /// \brief Retrieve counter type information for given counter name
1201
    counter_status registry::get_counter_type(
151✔
1202
        std::string const& name, counter_info& info, error_code& ec)
1203
    {
1204
        // create canonical type name
1205
        std::string type_name;
151✔
1206
        counter_status status = get_counter_type_name(name, type_name, ec);
151✔
1207
        if (!status_is_valid(status))
151✔
1208
            return status;
×
1209

1210
        // make sure the type of the counter is known to the registry
1211
        counter_type_map_type::iterator it = locate_counter_type(type_name);
151✔
1212
        if (it == countertypes_.end())
151✔
1213
        {
1214
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
1215
                "registry::get_counter_type", "unknown counter type {}",
1216
                type_name);
1217
            return counter_status::counter_type_unknown;
×
1218
        }
1219

1220
        info = (*it).second.info_;
151✔
1221

1222
        if (&ec != &throws)
151✔
1223
            ec = make_success_code();
64✔
1224
        return counter_status::valid_data;
151✔
1225
    }
151✔
1226

1227
    registry& registry::instance()
145,915✔
1228
    {
1229
        static registry instance_;
145,915✔
1230
        return instance_;
145,915✔
1231
    }
1232

1233
}}    // namespace hpx::performance_counters
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