xref: /aosp_15_r20/external/abseil-cpp/absl/log/internal/vlog_config.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
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.
VLogSite(const char * f)63   explicit constexpr VLogSite(const char* f)
64       : 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
IsEnabled(int level)72   bool IsEnabled(int level) {
73     int stale_v = v_.load(std::memory_order_relaxed);
74     if (ABSL_PREDICT_TRUE(level > stale_v)) {
75       return false;
76     }
77 
78     // We put everything other than the fast path, i.e. vlogging is initialized
79     // but not on, behind an out-of-line function to reduce code size.
80     // "level" is almost always a call-site constant, so we can save a bit
81     // of code space by special-casing for a few common levels.
82 #if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)
83     if (__builtin_constant_p(level)) {
84       if (level == 0) return SlowIsEnabled0(stale_v);
85       if (level == 1) return SlowIsEnabled1(stale_v);
86       if (level == 2) return SlowIsEnabled2(stale_v);
87       if (level == 3) return SlowIsEnabled3(stale_v);
88       if (level == 4) return SlowIsEnabled4(stale_v);
89       if (level == 5) return SlowIsEnabled5(stale_v);
90     }
91 #endif
92     return SlowIsEnabled(stale_v, level);
93   }
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_
164