tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_