conditions.h (11791B)
1 // Copyright 2022 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: log/internal/conditions.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This file contains implementation of conditional log statements, like LOG_IF 20 // including all the ABSL_LOG_INTERNAL_..._CONDITION_... macros and 21 // various condition classes like LogEveryNState. 22 23 #ifndef ABSL_LOG_INTERNAL_CONDITIONS_H_ 24 #define ABSL_LOG_INTERNAL_CONDITIONS_H_ 25 26 #if defined(_WIN32) || defined(__hexagon__) 27 #include <cstdlib> 28 #else 29 #include <unistd.h> 30 #endif 31 #include <stdlib.h> 32 33 #include <atomic> 34 #include <cstdint> 35 36 #include "absl/base/attributes.h" 37 #include "absl/base/config.h" 38 #include "absl/log/internal/voidify.h" 39 40 // `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a 41 // temporary `LogMessage` instantiation followed by zero or more streamed 42 // expressions. This definition is tricky to read correctly. It evaluates to 43 // either 44 // 45 // (void)0; 46 // 47 // or 48 // 49 // ::absl::log_internal::Voidify() && 50 // ::absl::log_internal::LogMessage(...) << "the user's message"; 51 // 52 // If the condition is evaluable at compile time, as is often the case, it 53 // compiles away to just one side or the other. 54 // 55 // Although this is not used anywhere a statement (e.g. `if`) could not go, 56 // the ternary expression does a better job avoiding spurious diagnostics 57 // (dangling else, missing switch case) and preserving noreturn semantics (e.g. 58 // on `LOG(FATAL)`) without requiring braces. 59 // 60 // The `switch` ensures that this expansion is the beginning of a statement (as 61 // opposed to an expression) and prevents shenanigans like 62 // `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`. The apparently-redundant 63 // `default` case makes the condition more amenable to Clang dataflow analysis. 64 #define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \ 65 switch (0) \ 66 case 0: \ 67 default: \ 68 !(condition) ? (void)0 : ::absl::log_internal::Voidify() && 69 70 // `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like 71 // `ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable 72 // declarations, including a local static object which stores the state needed 73 // to implement the stateful macros like `LOG_EVERY_N`. 74 // 75 // `for`-loops are used to declare scoped variables without braces (to permit 76 // streaming into the macro's expansion) and without the dangling-`else` 77 // problems/diagnostics that come with `if`. 78 // 79 // Two more variables are declared in separate `for`-loops: 80 // 81 // * `COUNTER` implements a streamable token whose value when streamed is the 82 // number of times execution has passed through the macro. 83 // * A boolean flag is used to prevent any of the `for`-loops from ever actually 84 // looping. 85 #define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition) \ 86 for (bool absl_log_internal_stateful_condition_do_log(condition); \ 87 absl_log_internal_stateful_condition_do_log; \ 88 absl_log_internal_stateful_condition_do_log = false) \ 89 ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL 90 #define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...) \ 91 for (static ::absl::log_internal::Log##kind##State \ 92 absl_log_internal_stateful_condition_state; \ 93 absl_log_internal_stateful_condition_do_log && \ 94 absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \ 95 absl_log_internal_stateful_condition_do_log = false) \ 96 for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED = \ 97 absl_log_internal_stateful_condition_state.counter(); \ 98 absl_log_internal_stateful_condition_do_log; \ 99 absl_log_internal_stateful_condition_do_log = false) \ 100 ::absl::log_internal::Voidify() && 101 102 // `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the 103 // macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g. 104 // `ABSL_MIN_LOG_LEVEL`) into a single boolean expression. We could chain 105 // ternary operators instead, however some versions of Clang sometimes issue 106 // spurious diagnostics after such expressions due to a control flow analysis 107 // bug. 108 #ifdef ABSL_MIN_LOG_LEVEL 109 #define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \ 110 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 111 (condition) && ::absl::LogSeverity::kInfo >= \ 112 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL)) 113 #define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \ 114 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 115 (condition) && ::absl::LogSeverity::kWarning >= \ 116 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL)) 117 #define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \ 118 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 119 (condition) && ::absl::LogSeverity::kError >= \ 120 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL)) 121 #define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \ 122 ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) 123 // NOTE: Use ternary operators instead of short-circuiting to mitigate 124 // https://bugs.llvm.org/show_bug.cgi?id=51928. 125 #define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \ 126 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 127 ((condition) \ 128 ? (::absl::LogSeverity::kFatal >= \ 129 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \ 130 ? true \ 131 : (::absl::log_internal::AbortQuietly(), false)) \ 132 : false)) 133 // NOTE: Use ternary operators instead of short-circuiting to mitigate 134 // https://bugs.llvm.org/show_bug.cgi?id=51928. 135 #define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \ 136 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 137 ((condition) \ 138 ? (::absl::LogSeverity::kFatal >= \ 139 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \ 140 ? true \ 141 : (::absl::log_internal::ExitQuietly(), false)) \ 142 : false)) 143 #define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ 144 ABSL_LOG_INTERNAL_##type##_CONDITION( \ 145 (ABSL_ASSUME(absl::kLogDebugFatal == absl::LogSeverity::kError || \ 146 absl::kLogDebugFatal == absl::LogSeverity::kFatal), \ 147 (condition) && \ 148 (::absl::kLogDebugFatal >= \ 149 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ 150 (::absl::kLogDebugFatal == ::absl::LogSeverity::kFatal && \ 151 (::absl::log_internal::AbortQuietly(), false))))) 152 153 #define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ 154 for (int absl_log_internal_severity_loop = 1; \ 155 absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ 156 for (const absl::LogSeverity absl_log_internal_severity = \ 157 ::absl::NormalizeLogSeverity(severity); \ 158 absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ 159 ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL 160 #define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \ 161 ABSL_LOG_INTERNAL_##type##_CONDITION(( \ 162 (condition) && \ 163 (absl_log_internal_severity >= \ 164 static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ 165 (absl_log_internal_severity == ::absl::LogSeverity::kFatal && \ 166 (::absl::log_internal::AbortQuietly(), false))))) 167 #else // ndef ABSL_MIN_LOG_LEVEL 168 #define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \ 169 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 170 #define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \ 171 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 172 #define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \ 173 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 174 #define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \ 175 ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) 176 #define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \ 177 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 178 #define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \ 179 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 180 #define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \ 181 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 182 #define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ 183 for (int absl_log_internal_severity_loop = 1; \ 184 absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ 185 for (const absl::LogSeverity absl_log_internal_severity = \ 186 ::absl::NormalizeLogSeverity(severity); \ 187 absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ 188 ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL 189 #define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \ 190 ABSL_LOG_INTERNAL_##type##_CONDITION(condition) 191 #endif // ndef ABSL_MIN_LOG_LEVEL 192 193 namespace absl { 194 ABSL_NAMESPACE_BEGIN 195 namespace log_internal { 196 197 // Stateful condition class name should be "Log" + name + "State". 198 class LogEveryNState final { 199 public: 200 bool ShouldLog(int n); 201 uint32_t counter() { return counter_.load(std::memory_order_relaxed); } 202 203 private: 204 std::atomic<uint32_t> counter_{0}; 205 }; 206 207 class LogFirstNState final { 208 public: 209 bool ShouldLog(int n); 210 uint32_t counter() { return counter_.load(std::memory_order_relaxed); } 211 212 private: 213 std::atomic<uint32_t> counter_{0}; 214 }; 215 216 class LogEveryPow2State final { 217 public: 218 bool ShouldLog(); 219 uint32_t counter() { return counter_.load(std::memory_order_relaxed); } 220 221 private: 222 std::atomic<uint32_t> counter_{0}; 223 }; 224 225 class LogEveryNSecState final { 226 public: 227 bool ShouldLog(double seconds); 228 uint32_t counter() { return counter_.load(std::memory_order_relaxed); } 229 230 private: 231 std::atomic<uint32_t> counter_{0}; 232 // Cycle count according to CycleClock that we should next log at. 233 std::atomic<int64_t> next_log_time_cycles_{0}; 234 }; 235 236 // Helper routines to abort the application quietly 237 238 [[noreturn]] inline void AbortQuietly() { abort(); } 239 [[noreturn]] inline void ExitQuietly() { _exit(1); } 240 } // namespace log_internal 241 ABSL_NAMESPACE_END 242 } // namespace absl 243 244 #endif // ABSL_LOG_INTERNAL_CONDITIONS_H_