Coverage Report

Created: 2024-09-23 06:29

/src/abseil-cpp/absl/log/internal/vlog_config.h
Line
Count
Source (jump to first uncovered line)
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
// vlog_config.h
17
// -----------------------------------------------------------------------------
18
//
19
// This header file defines `VLogSite`, a public primitive that represents
20
// a callsite for the `VLOG` family of macros and related libraries.
21
// It also declares and defines multiple internal utilities used to implement
22
// `VLOG`, such as `VLogSiteManager`.
23
24
#ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
25
#define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
26
27
// IWYU pragma: private, include "absl/log/log.h"
28
29
#include <atomic>
30
#include <cstdint>
31
#include <functional>
32
#include <limits>
33
#include <type_traits>
34
35
#include "absl/base/attributes.h"
36
#include "absl/base/config.h"
37
#include "absl/base/optimization.h"
38
#include "absl/base/thread_annotations.h"
39
#include "absl/strings/string_view.h"
40
41
namespace absl {
42
ABSL_NAMESPACE_BEGIN
43
namespace log_internal {
44
45
class SyntheticBinary;
46
class VLogSite;
47
48
int RegisterAndInitialize(VLogSite* v);
49
void UpdateVLogSites();
50
constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)();
51
52
// Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call.
53
//
54
// Libraries that provide `VLOG`-like functionality should use this to
55
// efficiently handle --vmodule.
56
//
57
// VLogSite objects must not be destroyed until the program exits. Doing so will
58
// probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The
59
// recommendation is to make all such objects function-local statics.
60
class VLogSite final {
61
 public:
62
  // `f` must not be destroyed until the program exits.
63
  explicit constexpr VLogSite(const char* f)
64
0
      : file_(f), v_(kUninitialized), next_(nullptr) {}
65
  VLogSite(const VLogSite&) = delete;
66
  VLogSite& operator=(const VLogSite&) = delete;
67
68
  // Inlining the function yields a ~3x performance improvement at the cost of a
69
  // 1.5x code size increase at the call site.
70
  // Takes locks but does not allocate memory.
71
  ABSL_ATTRIBUTE_ALWAYS_INLINE
72
0
  bool IsEnabled(int level) {
73
0
    int stale_v = v_.load(std::memory_order_relaxed);
74
0
    if (ABSL_PREDICT_TRUE(level > stale_v)) {
75
0
      return false;
76
0
    }
77
0
78
0
    // We put everything other than the fast path, i.e. vlogging is initialized
79
0
    // but not on, behind an out-of-line function to reduce code size.
80
0
    // "level" is almost always a call-site constant, so we can save a bit
81
0
    // of code space by special-casing for a few common levels.
82
0
#if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)
83
0
    if (__builtin_constant_p(level)) {
84
0
      if (level == 0) return SlowIsEnabled0(stale_v);
85
0
      if (level == 1) return SlowIsEnabled1(stale_v);
86
0
      if (level == 2) return SlowIsEnabled2(stale_v);
87
0
      if (level == 3) return SlowIsEnabled3(stale_v);
88
0
      if (level == 4) return SlowIsEnabled4(stale_v);
89
0
      if (level == 5) return SlowIsEnabled5(stale_v);
90
0
    }
91
0
#endif
92
0
    return SlowIsEnabled(stale_v, level);
93
0
  }
94
95
 private:
96
  friend int log_internal::RegisterAndInitialize(VLogSite* v);
97
  friend void log_internal::UpdateVLogSites();
98
  friend class log_internal::SyntheticBinary;
99
  static constexpr int kUninitialized = (std::numeric_limits<int>::max)();
100
101
  // SlowIsEnabled performs slower checks to determine whether a log site is
102
  // enabled. Because it is expected to be called somewhat rarely
103
  // (comparatively), it is not inlined to save on code size.
104
  //
105
  // Prerequisites to calling SlowIsEnabled:
106
  //   1) stale_v is uninitialized OR
107
  //   2) stale_v is initialized and >= level (meaning we must log).
108
  // Takes locks but does not allocate memory.
109
  ABSL_ATTRIBUTE_NOINLINE
110
  bool SlowIsEnabled(int stale_v, int level);
111
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v);
112
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v);
113
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v);
114
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v);
115
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v);
116
  ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);
117
118
  // This object is too size-sensitive to use absl::string_view.
119
  const char* const file_;
120
  std::atomic<int> v_;
121
  std::atomic<VLogSite*> next_;
122
};
123
static_assert(std::is_trivially_destructible<VLogSite>::value,
124
              "VLogSite must be trivially destructible");
125
126
// Returns the current verbose log level of `file`.
127
// Does not allocate memory.
128
int VLogLevel(absl::string_view file);
129
130
// Registers a site `v` to get updated as `vmodule` and `v` change.  Also
131
// initializes the site based on their current values, and returns that result.
132
// Does not allocate memory.
133
int RegisterAndInitialize(VLogSite* v);
134
135
// Allocates memory.
136
void UpdateVLogSites();
137
138
// Completely overwrites the saved value of `vmodule`.
139
// Allocates memory.
140
void UpdateVModule(absl::string_view vmodule);
141
142
// Updates the global verbosity level to `v` and returns the prior value.
143
// Allocates memory.
144
int UpdateGlobalVLogLevel(int v);
145
146
// Atomically prepends `module_pattern=log_level` to the start of vmodule.
147
// Returns the prior value for `module_pattern` if there was an exact match and
148
// `global_v` otherwise.
149
// Allocates memory.
150
int PrependVModule(absl::string_view module_pattern, int log_level);
151
152
// Registers `on_update` to be called whenever `v` or `vmodule` change.
153
// Allocates memory.
154
void OnVLogVerbosityUpdate(std::function<void()> cb);
155
156
// Does not allocate memory.
157
VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v);
158
159
}  // namespace log_internal
160
ABSL_NAMESPACE_END
161
}  // namespace absl
162
163
#endif  // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_