-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.h
128 lines (108 loc) · 3.99 KB
/
utils.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#ifndef IMPOSSIBLE_PROGRAMS_UTILS_H
#define IMPOSSIBLE_PROGRAMS_UTILS_H
#define PRINT_EXPR_IMPL(expr, fmt_str, conversion) \
do { \
auto __val = (expr); \
printf("%s = " fmt_str "\n", #expr, conversion); \
} while (false)
#define PRINT_BIT_EXPR(expr) \
PRINT_EXPR_IMPL(expr, "%s", __val ? "true" : "false")
#define PRINT_NAT_EXPR(expr) PRINT_EXPR_IMPL(expr, "%llu", __val)
class Timer {
public:
explicit Timer(const char *id) : id_(id) {
start_ = std::chrono::high_resolution_clock::now();
}
~Timer() {
TimePointTy stop = std::chrono::high_resolution_clock::now();
double us =
std::chrono::duration_cast<std::chrono::microseconds>(stop - start_)
.count();
std::array<const char *, 3> unit = {"us", "ms", "s"};
int unit_idx;
for (unit_idx = 0; unit_idx < 3; unit_idx++) {
if (us < std::pow(1000, unit_idx)) {
break;
}
}
if (unit_idx != 0) {
unit_idx--;
}
printf("Time taken in %s: %0.3lf%s\n", id_, us / std::pow(1000, unit_idx),
unit[unit_idx]);
}
private:
using TimePointTy =
std::chrono::time_point<std::chrono::high_resolution_clock>;
TimePointTy start_;
const char *id_;
};
#define CREATE_TIMER() Timer __timer(__func__);
template <typename T> struct is_optional {
static constexpr bool value = false;
};
template <typename T> struct is_optional<std::optional<T>> {
static constexpr bool value = true;
};
// Macro that is a poor man's maybe monad. If DoFoo() returns a value of type
// std::optional<T> then you can use this macro like this:
//
// S DoBar(T);
//
// std::optional<S> Bar() {
// ASSIGN_OR_RETURN(T, var, DoFoo());
// return DoBar(var);
// }
//
// Which is equivalent to:
//
// S DoBar(T);
//
// std::optional<S> Bar() {
// T var;
// std::optional<T> tmp = DoFoo();
// if (!tmp.has_value()) {
// return std::nullopt;
// }
// var = *tmp;
// return DoBar(var);
// }
#define ASSIGN_OR_RETURN(type, var, expr) \
static_assert(is_optional<decltype(expr)>::value); \
type var; \
do { \
auto __tmp = (expr); \
if (!__tmp.has_value()) { \
return std::nullopt; \
} \
var = *__tmp; \
} while (false)
#ifdef ENABLE_LOG
#define LOG(str, ...) \
printf("[%s/%s:%d] " str "\n", __FILE__, __func__, __LINE__, __VA_ARGS__)
#else
#define LOG(str, ...) (void)0
#endif
// Used to check that we have only one active call to a function in a thread.
// Don't use this class directly, use ASSERT_ONLY_ONE_ACTIVE_CALL instead.
template <int *FuncId> class AssertOnlyOneActiveCall {
public:
explicit AssertOnlyOneActiveCall(const char *function_name) {
if (find_is_active_) {
printf("Multiple active %s frames on the same thread!\n", function_name);
abort();
}
find_is_active_ = true;
}
~AssertOnlyOneActiveCall() { find_is_active_ = false; }
private:
static thread_local bool find_is_active_;
};
template <int *FuncId>
/*static*/ bool thread_local AssertOnlyOneActiveCall<FuncId>::find_is_active_ =
false;
#define ASSERT_ONLY_ONE_ACTIVE_CALL() \
static int __only_one_active_call_id; \
AssertOnlyOneActiveCall<&__only_one_active_call_id> __only_one_active_call( \
__func__);
#endif