conditions.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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 Y_ABSL_LOG_INTERNAL_..._CONDITION_... macros and
  21. // various condition classes like LogEveryNState.
  22. #ifndef Y_ABSL_LOG_INTERNAL_CONDITIONS_H_
  23. #define Y_ABSL_LOG_INTERNAL_CONDITIONS_H_
  24. #if defined(_WIN32) || defined(__hexagon__)
  25. #include <cstdlib>
  26. #else
  27. #include <unistd.h>
  28. #endif
  29. #include <stdlib.h>
  30. #include <atomic>
  31. #include <cstdint>
  32. #include "y_absl/base/attributes.h"
  33. #include "y_absl/base/config.h"
  34. #include "y_absl/log/internal/voidify.h"
  35. // `Y_ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
  36. // temporary `LogMessage` instantiation followed by zero or more streamed
  37. // expressions. This definition is tricky to read correctly. It evaluates to
  38. // either
  39. //
  40. // (void)0;
  41. //
  42. // or
  43. //
  44. // ::y_absl::log_internal::Voidify() &&
  45. // ::y_absl::log_internal::LogMessage(...) << "the user's message";
  46. //
  47. // If the condition is evaluable at compile time, as is often the case, it
  48. // compiles away to just one side or the other.
  49. //
  50. // Although this is not used anywhere a statement (e.g. `if`) could not go,
  51. // the ternary expression does a better job avoiding spurious diagnostics
  52. // (dangling else, missing switch case) and preserving noreturn semantics (e.g.
  53. // on `LOG(FATAL)`) without requiring braces.
  54. //
  55. // The `switch` ensures that this expansion is the beginning of a statement (as
  56. // opposed to an expression) and prevents shenanigans like
  57. // `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`. The apparently-redundant
  58. // `default` case makes the condition more amenable to Clang dataflow analysis.
  59. #define Y_ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
  60. switch (0) \
  61. case 0: \
  62. default: \
  63. !(condition) ? (void)0 : ::y_absl::log_internal::Voidify()&&
  64. // `Y_ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
  65. // `Y_ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable
  66. // declarations, including a local static object which stores the state needed
  67. // to implement the stateful macros like `LOG_EVERY_N`.
  68. //
  69. // `for`-loops are used to declare scoped variables without braces (to permit
  70. // streaming into the macro's expansion) and without the dangling-`else`
  71. // problems/diagnostics that come with `if`.
  72. //
  73. // Two more variables are declared in separate `for`-loops:
  74. //
  75. // * `COUNTER` implements a streamable token whose value when streamed is the
  76. // number of times execution has passed through the macro.
  77. // * A boolean flag is used to prevent any of the `for`-loops from ever actually
  78. // looping.
  79. #define Y_ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition) \
  80. for (bool absl_log_internal_stateful_condition_do_log(condition); \
  81. absl_log_internal_stateful_condition_do_log; \
  82. absl_log_internal_stateful_condition_do_log = false) \
  83. Y_ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL
  84. #define Y_ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...) \
  85. for (static ::y_absl::log_internal::Log##kind##State \
  86. absl_log_internal_stateful_condition_state; \
  87. absl_log_internal_stateful_condition_do_log && \
  88. absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \
  89. absl_log_internal_stateful_condition_do_log = false) \
  90. for (const uint32_t COUNTER Y_ABSL_ATTRIBUTE_UNUSED = \
  91. absl_log_internal_stateful_condition_state.counter(); \
  92. absl_log_internal_stateful_condition_do_log; \
  93. absl_log_internal_stateful_condition_do_log = false)
  94. // `Y_ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
  95. // macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
  96. // `Y_ABSL_MIN_LOG_LEVEL`) into a single boolean expression. We could chain
  97. // ternary operators instead, however some versions of Clang sometimes issue
  98. // spurious diagnostics after such expressions due to a control flow analysis
  99. // bug.
  100. #ifdef Y_ABSL_MIN_LOG_LEVEL
  101. #define Y_ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
  102. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  103. (condition) && ::y_absl::LogSeverity::kInfo >= \
  104. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL))
  105. #define Y_ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
  106. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  107. (condition) && ::y_absl::LogSeverity::kWarning >= \
  108. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL))
  109. #define Y_ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
  110. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  111. (condition) && ::y_absl::LogSeverity::kError >= \
  112. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL))
  113. // NOTE: Use ternary operators instead of short-circuiting to mitigate
  114. // https://bugs.llvm.org/show_bug.cgi?id=51928.
  115. #define Y_ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
  116. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  117. ((condition) \
  118. ? (::y_absl::LogSeverity::kFatal >= \
  119. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL) \
  120. ? true \
  121. : (::y_absl::log_internal::AbortQuietly(), false)) \
  122. : false))
  123. // NOTE: Use ternary operators instead of short-circuiting to mitigate
  124. // https://bugs.llvm.org/show_bug.cgi?id=51928.
  125. #define Y_ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
  126. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  127. ((condition) \
  128. ? (::y_absl::LogSeverity::kFatal >= \
  129. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL) \
  130. ? true \
  131. : (::y_absl::log_internal::ExitQuietly(), false)) \
  132. : false))
  133. #define Y_ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \
  134. Y_ABSL_LOG_INTERNAL_##type##_CONDITION( \
  135. (Y_ABSL_ASSUME(y_absl::kLogDebugFatal == y_absl::LogSeverity::kError || \
  136. y_absl::kLogDebugFatal == y_absl::LogSeverity::kFatal), \
  137. (condition) && \
  138. (::y_absl::kLogDebugFatal >= \
  139. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL) || \
  140. (::y_absl::kLogDebugFatal == ::y_absl::LogSeverity::kFatal && \
  141. (::y_absl::log_internal::AbortQuietly(), false)))))
  142. #define Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
  143. for (int absl_log_internal_severity_loop = 1; \
  144. absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
  145. for (const y_absl::LogSeverity absl_log_internal_severity = \
  146. ::y_absl::NormalizeLogSeverity(severity); \
  147. absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
  148. Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
  149. #define Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
  150. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(( \
  151. (condition) && \
  152. (absl_log_internal_severity >= \
  153. static_cast<::y_absl::LogSeverity>(Y_ABSL_MIN_LOG_LEVEL) || \
  154. (absl_log_internal_severity == ::y_absl::LogSeverity::kFatal && \
  155. (::y_absl::log_internal::AbortQuietly(), false)))))
  156. #else // ndef Y_ABSL_MIN_LOG_LEVEL
  157. #define Y_ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
  158. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  159. #define Y_ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
  160. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  161. #define Y_ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
  162. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  163. #define Y_ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
  164. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  165. #define Y_ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
  166. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  167. #define Y_ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \
  168. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  169. #define Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
  170. for (int absl_log_internal_severity_loop = 1; \
  171. absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
  172. for (const y_absl::LogSeverity absl_log_internal_severity = \
  173. ::y_absl::NormalizeLogSeverity(severity); \
  174. absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
  175. Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
  176. #define Y_ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
  177. Y_ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
  178. #endif // ndef Y_ABSL_MIN_LOG_LEVEL
  179. namespace y_absl {
  180. Y_ABSL_NAMESPACE_BEGIN
  181. namespace log_internal {
  182. // Stateful condition class name should be "Log" + name + "State".
  183. class LogEveryNState final {
  184. public:
  185. bool ShouldLog(int n);
  186. uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
  187. private:
  188. std::atomic<uint32_t> counter_{0};
  189. };
  190. class LogFirstNState final {
  191. public:
  192. bool ShouldLog(int n);
  193. uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
  194. private:
  195. std::atomic<uint32_t> counter_{0};
  196. };
  197. class LogEveryPow2State final {
  198. public:
  199. bool ShouldLog();
  200. uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
  201. private:
  202. std::atomic<uint32_t> counter_{0};
  203. };
  204. class LogEveryNSecState final {
  205. public:
  206. bool ShouldLog(double seconds);
  207. uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
  208. private:
  209. std::atomic<uint32_t> counter_{0};
  210. // Cycle count according to CycleClock that we should next log at.
  211. std::atomic<int64_t> next_log_time_cycles_{0};
  212. };
  213. // Helper routines to abort the application quietly
  214. [[noreturn]] inline void AbortQuietly() { abort(); }
  215. [[noreturn]] inline void ExitQuietly() { _exit(1); }
  216. } // namespace log_internal
  217. Y_ABSL_NAMESPACE_END
  218. } // namespace y_absl
  219. #endif // Y_ABSL_LOG_INTERNAL_CONDITIONS_H_