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

STEllAR-GROUP / hpx / #852

17 Dec 2022 04:43PM UTC coverage: 85.912% (-0.7%) from 86.568%
#852

push

StellarBot
Merge #6106

6106: Modernizing modules of levels 0 to 5 r=hkaiser a=hkaiser

- flyby: HPX_FORWARD/HPX_MOVE now expand to std::forward and std::move if those are implemented as builtin functions

working towards #5497

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

87 of 87 new or added lines in 24 files covered. (100.0%)

173152 of 201546 relevant lines covered (85.91%)

1910264.28 hits per line

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

92.37
/libs/core/debugging/include/hpx/debugging/print.hpp
1
//  Copyright (c) 2019-2020 John Biddiscombe
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#pragma once
8

9
#include <hpx/config.hpp>
10

11
#include <array>
12
#include <chrono>
13
#include <cstddef>
14
#include <cstdint>
15
#include <iostream>
16
#include <sstream>
17
#include <string>
18
#include <tuple>
19
#include <type_traits>
20
#include <utility>
21
#include <vector>
22

23
// ------------------------------------------------------------
24
// This file provides a simple to use printf style debugging
25
// tool that can be used on a per file basis to enable output.
26
// It is not intended to be exposed to users, but rather as
27
// an aid for hpx development.
28
// ------------------------------------------------------------
29
// Usage: Instantiate a debug print object at the top of a file
30
// using a template param of true/false to enable/disable output.
31
// When the template parameter is false, the optimizer will
32
// not produce code and so the impact is nil.
33
//
34
// static hpx::debug::enable_print<true> spq_deb("SUBJECT");
35
//
36
// Later in code you may print information using
37
//
38
//             spq_deb.debug(str<16>("cleanup_terminated"), "v1"
39
//                  , "D" , dec<2>(domain_num)
40
//                  , "Q" , dec<3>(q_index)
41
//                  , "thread_num", dec<3>(local_num));
42
//
43
// various print formatters (dec/hex/str) are supplied to make
44
// the output regular and aligned for easy parsing/scanning.
45
//
46
// In tight loops, huge amounts of debug information might be
47
// produced, so a simple timer based output is provided
48
// To instantiate a timed output
49
//      static auto getnext = spq_deb.make_timer(1
50
//              , str<16>("get_next_thread"));
51
// then inside a tight loop
52
//      spq_deb.timed(getnext, dec<>(thread_num));
53
// The output will only be produced every N seconds
54
// ------------------------------------------------------------
55

56
// Used to wrap function call parameters to prevent evaluation
57
// when debugging is disabled
58
#define HPX_DP_LAZY(Expr, printer) printer.eval([&] { return Expr; })
59

60
// ------------------------------------------------------------
61
/// \cond NODETAIL
62
namespace hpx::debug {
63

64
    // ------------------------------------------------------------------
65
    // format as zero padded int
66
    // ------------------------------------------------------------------
67
    namespace detail {
68

69
        template <typename Int>
70
        HPX_CORE_EXPORT void print_dec(std::ostream& os, Int const& v, int n);
71

72
        template <int N, typename T>
73
        struct dec
74
        {
75
            explicit constexpr dec(T const& v) noexcept
32,477,653✔
76
              : data_(v)
32,509,595✔
77
            {
78
            }
32,509,595✔
79

80
            T const& data_;
81

82
            friend std::ostream& operator<<(
3,369✔
83
                std::ostream& os, dec<N, T> const& d)
84
            {
85
                detail::print_dec(os, d.data_, N);
3,364✔
86
                return os;
3,364✔
87
            }
88
        };
89
    }    // namespace detail
90

91
    template <int N = 2, typename T>
92
    constexpr detail::dec<N, T> dec(T const& v) noexcept
32,227,255✔
93
    {
94
        return detail::dec<N, T>(v);
32,240,887✔
95
    }
96

97
    // ------------------------------------------------------------------
98
    // format as pointer
99
    // ------------------------------------------------------------------
100
    struct ptr
101
    {
102
        HPX_CORE_EXPORT explicit ptr(void const* v) noexcept;
103
        HPX_CORE_EXPORT explicit ptr(std::uintptr_t v) noexcept;
104

105
        void const* data_;
106

107
        HPX_CORE_EXPORT friend std::ostream& operator<<(
108
            std::ostream& os, ptr const& d);
109
    };
110

111
    // ------------------------------------------------------------------
112
    // format as zero padded hex
113
    // ------------------------------------------------------------------
114
    namespace detail {
115

116
        template <typename Int>
117
        HPX_CORE_EXPORT void print_hex(std::ostream& os, Int v, int n);
118

119
        template <int N = 4, typename T = int, typename Enable = void>
120
        struct hex;
121

122
        template <int N, typename T>
123
        struct hex<N, T, std::enable_if_t<!std::is_pointer_v<T>>>
124
        {
125
            explicit constexpr hex(T const& v) noexcept
980✔
126
              : data_(v)
980✔
127
            {
128
            }
980✔
129

130
            T const& data_;
131

132
            friend std::ostream& operator<<(
977✔
133
                std::ostream& os, hex<N, T> const& d)
134
            {
135
                detail::print_hex(os, d.data_, N);
977✔
136
                return os;
977✔
137
            }
138
        };
139

140
        HPX_CORE_EXPORT void print_ptr(std::ostream& os, void* v, int n);
141

142
        template <int N, typename T>
143
        struct hex<N, T, std::enable_if_t<std::is_pointer_v<T>>>
144
        {
145
            explicit constexpr hex(T const& v) noexcept
1,042✔
146
              : data_(v)
1,042✔
147
            {
148
            }
1,042✔
149

150
            T const& data_;
151

152
            friend std::ostream& operator<<(
290✔
153
                std::ostream& os, hex<N, T> const& d)
154
            {
155
                detail::print_ptr(os, d.data_, N);
290✔
156
                return os;
290✔
157
            }
158
        };
159
    }    // namespace detail
160

161
    template <int N = 4, typename T>
162
    constexpr detail::hex<N, T> hex(T const& v) noexcept
1,044✔
163
    {
164
        return detail::hex<N, T>(v);
1,044✔
165
    }
166

167
    // ------------------------------------------------------------------
168
    // format as binary bits
169
    // ------------------------------------------------------------------
170
    namespace detail {
171

172
        template <typename Int>
173
        HPX_CORE_EXPORT void print_bin(std::ostream& os, Int v, int n);
174

175
        template <int N = 8, typename T = int>
176
        struct bin
177
        {
178
            explicit constexpr bin(T const& v) noexcept
130✔
179
              : data_(v)
130✔
180
            {
181
            }
130✔
182

183
            T const& data_;
184

185
            friend std::ostream& operator<<(
36✔
186
                std::ostream& os, bin<N, T> const& d)
187
            {
188
                detail::print_bin(os, d.data_, N);
36✔
189
                return os;
36✔
190
            }
191
        };
192
    }    // namespace detail
193

194
    template <int N = 8, typename T>
195
    constexpr detail::bin<N, T> bin(T const& v) noexcept
130✔
196
    {
197
        return detail::bin<N, T>(v);
130✔
198
    }
199

200
    // ------------------------------------------------------------------
201
    // format as padded string
202
    // ------------------------------------------------------------------
203
    namespace detail {
204

205
        HPX_CORE_EXPORT void print_str(std::ostream& os, char const* v, int n);
206
    }
207

208
    template <int N = 20>
209
    struct str
210
    {
211
        explicit constexpr str(char const* v) noexcept
2,592,109✔
212
          : data_(v)
2,592,452✔
213
        {
214
        }
2,592,452✔
215

216
        char const* data_;
217

218
        friend std::ostream& operator<<(std::ostream& os, str<N> const& d)
1,992✔
219
        {
220
            detail::print_str(os, d.data_, N);
1,990✔
221
            return os;
1,990✔
222
        }
223
    };
224

225
    // ------------------------------------------------------------------
226
    // format as ip address
227
    // ------------------------------------------------------------------
228
    struct ipaddr
229
    {
230
        HPX_CORE_EXPORT explicit ipaddr(void const* a) noexcept;
231
        HPX_CORE_EXPORT explicit ipaddr(std::uint32_t a) noexcept;
232

233
        std::uint8_t const* data_;
234
        std::uint32_t const ipdata_;
235

236
        HPX_CORE_EXPORT friend std::ostream& operator<<(
237
            std::ostream& os, ipaddr const& p);
238
    };
239

240
    // ------------------------------------------------------------------
241
    // helper class for printing time since start
242
    // ------------------------------------------------------------------
243
    namespace detail {
244

245
        struct current_time_print_helper
246
        {
247
            HPX_CORE_EXPORT friend std::ostream& operator<<(
248
                std::ostream& os, current_time_print_helper const&);
249
        };
250
    }    // namespace detail
251

252
    // ------------------------------------------------------------------
253
    // helper function for printing CRC32
254
    // ------------------------------------------------------------------
255
    constexpr inline std::uint32_t crc32(void const*, std::size_t) noexcept
×
256
    {
257
        return 0;
×
258
    }
259

260
    // ------------------------------------------------------------------
261
    // helper function for printing short memory dump and crc32
262
    // useful for debugging corruptions in buffers during
263
    // rma or other transfers
264
    // ------------------------------------------------------------------
265
    struct mem_crc32
266
    {
267
        HPX_CORE_EXPORT mem_crc32(
268
            void const* a, std::size_t len, char const* txt) noexcept;
269

270
        std::uint64_t const* addr_;
271
        std::size_t const len_;
272
        char const* txt_;
273

274
        HPX_CORE_EXPORT friend std::ostream& operator<<(
275
            std::ostream& os, mem_crc32 const& p);
276
    };
277

278
    namespace detail {
279

280
        template <typename TupleType, std::size_t... I>
281
        void tuple_print(
42✔
282
            std::ostream& os, TupleType const& t, std::index_sequence<I...>)
283
        {
284
            (..., (os << (I == 0 ? "" : " ") << std::get<I>(t)));
42✔
285
        }
42✔
286

287
        template <typename... Args>
288
        void tuple_print(std::ostream& os, const std::tuple<Args...>& t)
41✔
289
        {
290
            tuple_print(os, t, std::make_index_sequence<sizeof...(Args)>());
41✔
291
        }
41✔
292
    }    // namespace detail
293

294
    namespace detail {
295

296
        // ------------------------------------------------------------------
297
        // helper class for printing time since start
298
        // ------------------------------------------------------------------
299
        struct hostname_print_helper
300
        {
301
            HPX_CORE_EXPORT char const* get_hostname() const;
302
            HPX_CORE_EXPORT int guess_rank() const;
303

304
            HPX_CORE_EXPORT friend std::ostream& operator<<(
305
                std::ostream& os, hostname_print_helper const& h);
306
        };
307

308
        ///////////////////////////////////////////////////////////////////////
309
        HPX_CORE_EXPORT void register_print_info(void (*)(std::ostream&));
310
        HPX_CORE_EXPORT void generate_prefix(std::ostream& os);
311

312
        ///////////////////////////////////////////////////////////////////////
313
        template <typename... Args>
314
        void display(char const* prefix, Args const&... args)
997✔
315
        {
316
            // using a temp stream object with a single copy to cout at the end
317
            // prevents multiple threads from injecting overlapping text
318
            std::stringstream tempstream;
998✔
319
            tempstream << prefix;
998✔
320
            generate_prefix(tempstream);
1,009✔
321
            ((tempstream << args << " "), ...);
1,009✔
322
            tempstream << std::endl;
1,007✔
323
            std::cout << tempstream.str();
1,007✔
324
        }
1,010✔
325

326
        template <typename... Args>
327
        void debug(Args const&... args)
962✔
328
        {
329
            display("<DEB> ", args...);
961✔
330
        }
961✔
331

332
        template <typename... Args>
333
        void warning(Args const&... args)
334
        {
335
            display("<WAR> ", args...);
336
        }
337

338
        template <typename... Args>
339
        void error(Args const&... args)
×
340
        {
341
            display("<ERR> ", args...);
×
342
        }
×
343

344
        template <typename... Args>
345
        void scope(Args const&... args)
346
        {
347
            display("<SCO> ", args...);
348
        }
349

350
        template <typename... Args>
351
        void trace(Args const&... args)
352
        {
353
            display("<TRC> ", args...);
354
        }
355

356
        template <typename... Args>
357
        void timed(Args const&... args)
25✔
358
        {
359
            display("<TIM> ", args...);
27✔
360
        }
27✔
361
    }    // namespace detail
362

363
    template <typename... Args>
364
    struct scoped_var
365
    {
366
        // capture tuple elements by reference - no temp vars in constructor please
367
        char const* prefix_;
368
        std::tuple<Args const&...> const message_;
369
        std::string buffered_msg;
370

371
        //
372
        scoped_var(char const* p, Args const&... args)
1✔
373
          : prefix_(p)
1✔
374
          , message_(args...)
1✔
375
        {
376
            std::stringstream tempstream;
1✔
377
            detail::tuple_print(tempstream, message_);
1✔
378
            buffered_msg = tempstream.str();
1✔
379
            detail::display("<SCO> ", prefix_, debug::str<>(">> enter <<"),
1✔
380
                tempstream.str());
1✔
381
        }
1✔
382

383
        ~scoped_var()
1✔
384
        {
385
            detail::display(
1✔
386
                "<SCO> ", prefix_, debug::str<>("<< leave >>"), buffered_msg);
1✔
387
        }
1✔
388
    };
389

390
    template <typename... Args>
391
    struct timed_var
392
    {
393
        mutable std::chrono::steady_clock::time_point time_start_;
394
        double const delay_;
395
        std::tuple<Args...> const message_;
396
        //
397
        timed_var(double const& delay, Args const&... args)
6✔
398
          : time_start_(std::chrono::steady_clock::now())
6✔
399
          , delay_(delay)
6✔
400
          , message_(args...)
6✔
401
        {
402
        }
6✔
403

404
        bool elapsed(std::chrono::steady_clock::time_point const& now) const
14,180,165✔
405
        {
406
            double elapsed_ =
12,613,283✔
407
                std::chrono::duration_cast<std::chrono::duration<double>>(
12,613,283✔
408
                    now - time_start_)
12,613,283✔
409
                    .count();
12,613,283✔
410

411
            if (elapsed_ > delay_)
12,613,283✔
412
            {
413
                time_start_ = now;
26✔
414
                return true;
26✔
415
            }
416
            return false;
12,670,680✔
417
        }
12,672,565✔
418

419
        friend std::ostream& operator<<(
38✔
420
            std::ostream& os, timed_var<Args...> const& ti)
421
        {
422
            detail::tuple_print(os, ti.message_);
40✔
423
            return os;
40✔
424
        }
425
    };
426

427
    ///////////////////////////////////////////////////////////////////////////
428
    template <bool enable>
429
    struct enable_print;
430

431
    // when false, debug statements should produce no code
432
    template <>
433
    struct enable_print<false>
434
    {
435
        explicit constexpr enable_print(const char*) noexcept {}
436

437
        constexpr bool is_enabled() const noexcept
438
        {
439
            return false;
440
        }
441

442
        template <typename... Args>
443
        constexpr void debug(Args const&...) const noexcept
2,592,092✔
444
        {
445
        }
2,592,059✔
446

447
        template <typename... Args>
448
        constexpr void warning(Args const&...) const noexcept
449
        {
450
        }
451

452
        template <typename... Args>
453
        constexpr void trace(Args const&...) const noexcept
454
        {
455
        }
456

457
        template <typename... Args>
458
        constexpr void error(Args const&...) const noexcept
×
459
        {
460
        }
×
461

462
        template <typename... Args>
463
        constexpr void timed(Args const&...) const noexcept
29,867,934✔
464
        {
465
        }
29,967,794✔
466

467
        template <typename T>
468
        constexpr void array(
469
            std::string const&, std::vector<T> const&) const noexcept
470
        {
471
        }
472

473
        template <typename T, std::size_t N>
474
        constexpr void array(
475
            std::string const&, std::array<T, N> const&) const noexcept
476
        {
477
        }
478

479
        template <typename T>
480
        constexpr void array(
55✔
481
            std::string const&, T const*, std::size_t) const noexcept
482
        {
483
        }
55✔
484

485
        template <typename... Args>
486
        constexpr bool scope(Args const&...) noexcept
1✔
487
        {
488
            return true;
1✔
489
        }
490

491
        template <typename T, typename... Args>
492
        constexpr bool declare_variable(Args const&...) const noexcept
142,507✔
493
        {
494
            return true;
142,507✔
495
        }
496

497
        template <typename T, typename V>
498
        constexpr void set(T&, V const&) noexcept
142,507✔
499
        {
500
        }
142,507✔
501

502
        // @todo, return void so that timers have zero footprint when disabled
503
        template <typename... Args>
504
        constexpr int make_timer(const double, Args const&...) const noexcept
505
        {
506
            return 0;
507
        }
508

509
        template <typename Expr>
510
        constexpr bool eval(Expr const&) noexcept
10,451,014✔
511
        {
512
            return true;
10,451,014✔
513
        }
514
    };
515

516
    namespace detail {
517

518
        template <typename T>
519
        HPX_CORE_EXPORT void print_array(
520
            std::string const& name, T const* data, std::size_t size);
521
    }
522

523
    // when true, debug statements produce valid output
524
    template <>
525
    struct enable_print<true>
526
    {
527
    private:
528
        char const* prefix_;
529

530
    public:
531
        constexpr enable_print() noexcept
532
          : prefix_("")
533
        {
534
        }
535

536
        explicit constexpr enable_print(const char* p) noexcept
537
          : prefix_(p)
538
        {
539
        }
540

541
        constexpr bool is_enabled() const noexcept
542
        {
543
            return true;
544
        }
545

546
        template <typename... Args>
547
        constexpr void debug(Args const&... args) const
961✔
548
        {
549
            detail::debug(prefix_, args...);
961✔
550
        }
961✔
551

552
        template <typename... Args>
553
        constexpr void warning(Args const&... args) const
554
        {
555
            detail::warning(prefix_, args...);
556
        }
557

558
        template <typename... Args>
559
        constexpr void trace(Args const&... args) const
560
        {
561
            detail::trace(prefix_, args...);
562
        }
563

564
        template <typename... Args>
565
        constexpr void error(Args const&... args) const
×
566
        {
567
            detail::error(prefix_, args...);
×
568
        }
×
569

570
        template <typename... Args>
571
        scoped_var<Args...> scope(Args const&... args)
1✔
572
        {
573
            return scoped_var<Args...>(prefix_, args...);
1✔
574
        }
575

576
        template <typename... T, typename... Args>
577
        void timed(timed_var<T...> const& init, Args const&... args) const
14,766,306✔
578
        {
579
            auto now = std::chrono::steady_clock::now();
13,717,675✔
580
            if (init.elapsed(now))
13,717,675✔
581
            {
582
                detail::timed(prefix_, init, args...);
45✔
583
            }
45✔
584
        }
13,755,811✔
585

586
        template <typename T>
587
        void array(std::string const& name, std::vector<T> const& v) const
588
        {
589
            detail::print_array(name, v.data(), v.size());
590
        }
591

592
        template <typename T, std::size_t N>
593
        void array(std::string const& name, std::array<T, N> const& v) const
594
        {
595
            detail::print_array(name, v.data(), N);
596
        }
597

598
        template <typename T>
599
        void array(
600
            std::string const& name, T const* data, std::size_t size) const
601
        {
602
            detail::print_array(name, data, size);
603
        }
604

605
        template <typename T, typename... Args>
606
        T declare_variable(Args const&... args) const
8✔
607
        {
608
            return T(args...);
8✔
609
        }
610

611
        template <typename T, typename V>
612
        void set(T& var, V const& val)
8✔
613
        {
614
            var = val;
8✔
615
        }
8✔
616

617
        template <typename... Args>
618
        timed_var<Args...> make_timer(
6✔
619
            const double delay, const Args... args) const
620
        {
621
            return timed_var<Args...>(delay, args...);
6✔
622
        }
623

624
        template <typename Expr>
625
        auto eval(Expr const& e)
10,451,014✔
626
        {
627
            return e();
10,451,014✔
628
        }
629
    };
630
}    // namespace hpx::debug
631
/// \endcond
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