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

celerity / celerity-runtime / 12009901531

25 Nov 2024 12:20PM UTC coverage: 94.92% (+0.009%) from 94.911%
12009901531

push

github

fknorr
Add missing includes and consistently order them

We can't add the misc-include-cleaner lint because it causes too many
false positives with "interface headers" such as sycl.hpp.

3190 of 3626 branches covered (87.98%)

Branch coverage included in aggregate %.

7049 of 7161 relevant lines covered (98.44%)

1242183.17 hits per line

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

81.43
/src/utils.cc
1
#include "utils.h"
2

3
#include "log.h"
4
#include "types.h"
5

6
#include <atomic>
7
#include <cassert>
8
#include <cctype>
9
#include <cstddef>
10
#include <cstdlib>
11
#include <functional>
12
#include <iterator>
13
#include <memory>
14
#include <regex>
15
#include <stdexcept>
16
#include <stdlib.h>
17
#include <string>
18
#include <string_view>
19
#include <typeinfo>
20

21
#include <fmt/format.h>
22

23
#if !defined(_MSC_VER)
24
// Required for kernel name demangling in Clang
25
#include <cxxabi.h>
26
#endif
27

28

29
namespace celerity::detail::utils {
30

31
std::string get_simplified_type_name_from_pointer(const std::type_info& pointer_type_info) {
2,730✔
32
#if !defined(_MSC_VER)
33
        const std::unique_ptr<char, void (*)(void*)> demangle_buffer(abi::__cxa_demangle(pointer_type_info.name(), nullptr, nullptr, nullptr), std::free);
2,730✔
34
        std::string demangled_type_name = demangle_buffer.get();
8,190✔
35
#else
36
        std::string demangled_type_name = pointer_type_info.name();
37
#endif
38

39
        // get rid of the pointer "*"
40
        if(!demangled_type_name.empty() && demangled_type_name.back() == '*') { demangled_type_name.pop_back(); }
2,730!
41

42
        if(demangled_type_name.length() < 2) return demangled_type_name;
2,730!
43
        bool templated = false;
2,730✔
44
        // there are two options:
45
        // 1. the type is templated; in this case, the last character is ">" and we go back to the matching "<"
46
        std::string::size_type last_idx = demangled_type_name.length() - 1;
2,730✔
47
        if(demangled_type_name[last_idx] == '>') {
2,730✔
48
                templated = true;
46✔
49
                int open = 0;
46✔
50
                while(last_idx > 1) {
1,064!
51
                        last_idx--;
1,064✔
52
                        if(demangled_type_name[last_idx] == '>') { open++; }
1,064✔
53
                        if(demangled_type_name[last_idx] == '<') {
1,064✔
54
                                if(open > 0) {
54✔
55
                                        open--;
8✔
56
                                } else {
57
                                        last_idx--;
46✔
58
                                        break;
46✔
59
                                }
60
                        }
61
                }
62
        }
63
        // 2. the type isn't templated (or we just removed the template); in this case, we are interested in the part from the end to the last ":" (or the start)
64
        std::string::size_type start_idx = last_idx - 1;
2,730✔
65
        while(start_idx > 0 && demangled_type_name[start_idx - 1] != ':') {
51,766✔
66
                start_idx--;
49,036✔
67
        }
68
        // if the type was templated, we add a "<...>" to indicate that
69
        return demangled_type_name.substr(start_idx, last_idx - start_idx + 1) + (templated ? "<...>" : "");
5,460✔
70
}
2,730✔
71

72
std::string escape_for_dot_label(std::string str) {
431✔
73
        str = std::regex_replace(str, std::regex("&"), "&amp;");
431✔
74
        str = std::regex_replace(str, std::regex("<"), "&lt;");
431✔
75
        str = std::regex_replace(str, std::regex(">"), "&gt;");
431✔
76
        return str;
431✔
77
}
78

79
// LCOV_EXCL_START
80
[[noreturn]] void unreachable() {
81
        assert(!"executed unreachable code");
82
        abort();
83
}
84
// LCOV_EXCL_STOP
85

86
// The panic solution defaults to `log_and_abort`, but is set to `throw_logic_error` in test binaries. Since panics are triggered from celerity library code, we
87
// manage it in a global and decide which path to take at runtime. We have also considered deciding this at link time by defining a weak symbol (GCC
88
// __attribute__((weak))) in the library which is overwritten by a strong symbol in the test library, but decided against this because there is no equivalent in
89
// MSVC and we would have to resort to even dirtier linker hacks for that target.
90
std::atomic<panic_solution> g_panic_solution = panic_solution::log_and_abort; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
91

92
void set_panic_solution(panic_solution solution) { g_panic_solution.store(solution, std::memory_order_relaxed); }
13✔
93

94
[[noreturn]] void panic(const std::string& msg) {
29✔
95
        const auto solution = g_panic_solution.load(std::memory_order_relaxed);
29✔
96
        if(solution == panic_solution::throw_logic_error) {
29!
97
                throw std::logic_error(msg);
29✔
98
        } else /* panic_solution::log_and_abort */ {
99
                // LCOV_EXCL_START
100
                // Print directly instead of logging: The abort message must not be hidden by log level setting, and in tests would be captured without the logging
101
                // infrastructure having a chance of dumping the logs due to the abort.
102
                fmt::print(stderr, "celerity-runtime panic: {}\n", msg);
103
                std::abort();
104
                // LCOV_EXCL_STOP
105
        }
106
}
107

108
void report_error(const error_policy policy, const std::string& msg) {
34✔
109
        switch(policy) {
34!
110
        case error_policy::ignore: break;
×
111
        case error_policy::log_warning: CELERITY_WARN("{}", msg); break;
2!
112
        case error_policy::log_error: CELERITY_ERROR("{}", msg); break;
13!
113
        case error_policy::panic: panic(msg); break;
19✔
114
        }
115
}
15✔
116

117
std::string make_buffer_debug_label(const buffer_id bid, const std::string& name) {
377✔
118
        // if there is no name defined, the name will be the buffer id.
119
        // if there is a name we want "id name"
120
        return !name.empty() ? fmt::format("B{} \"{}\"", bid, name) : fmt::format("B{}", bid);
754✔
121
}
122

123
std::string make_task_debug_label(const task_type tt, const task_id tid, const std::string& debug_name, bool title_case) {
46✔
124
        const auto type_string = [tt] {
46✔
125
                switch(tt) {
46!
126
                case task_type::epoch: return "epoch";
×
127
                case task_type::host_compute: return "host-compute task";
8✔
128
                case task_type::device_compute: return "device kernel";
29✔
129
                case task_type::collective: return "collective host task";
7✔
130
                case task_type::master_node: return "master-node host task";
2✔
131
                case task_type::horizon: return "horizon";
×
132
                case task_type::fence: return "fence";
×
133
                default: return "unknown task";
×
134
                }
135
        }();
46✔
136

137
        auto label = fmt::format("{} T{}", type_string, tid);
46✔
138
        if(title_case) { label[0] = static_cast<char>(std::toupper(label[0])); }
46✔
139
        if(!debug_name.empty()) { fmt::format_to(std::back_inserter(label), " \"{}\"", debug_name); }
46✔
140
        return label;
92✔
141
}
×
142

143
std::string replace_all(const std::string_view& input, const std::string_view& pattern, const std::string_view& replacement) {
9✔
144
        if(pattern.empty()) return std::string(input);
15✔
145

146
        std::string output;
6✔
147
        output.reserve(input.size());
6✔
148
        size_t last_pos = 0;
6✔
149
        size_t pos = 0;
6✔
150
        while((pos = input.find(pattern, last_pos)) != std::string::npos) {
16✔
151
                output.append(input, last_pos, pos - last_pos);
10✔
152
                output.append(replacement);
10✔
153
                last_pos = pos + pattern.size();
10✔
154
        }
155
        output.append(input, last_pos);
6✔
156
        return output;
6✔
157
}
6✔
158

159
} // namespace celerity::detail::utils
160

161

162
// implemented here because types.h must not depend on utils.h
163
std::size_t std::hash<celerity::detail::transfer_id>::operator()(const celerity::detail::transfer_id& t) const noexcept {
7,917✔
164
        auto hash = std::hash<celerity::detail::task_id>{}(t.consumer_tid);
7,917✔
165
        celerity::detail::utils::hash_combine(hash, std::hash<celerity::detail::buffer_id>{}(t.bid));
7,917✔
166
        celerity::detail::utils::hash_combine(hash, std::hash<celerity::detail::reduction_id>{}(t.rid));
7,917✔
167
        return hash;
7,917✔
168
}
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