Coverage Report

Created: 2025-07-11 06:37

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