Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:14

0001 // Copyright 2021 The Abseil Authors
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //     https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
0016 #define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
0017 
0018 #include <atomic>
0019 #include <cstdint>
0020 
0021 #include "absl/base/config.h"
0022 
0023 namespace absl {
0024 ABSL_NAMESPACE_BEGIN
0025 namespace cord_internal {
0026 
0027 // CordzUpdateTracker tracks counters for Cord update methods.
0028 //
0029 // The purpose of CordzUpdateTracker is to track the number of calls to methods
0030 // updating Cord data for sampled cords. The class internally uses 'lossy'
0031 // atomic operations: Cord is thread-compatible, so there is no need to
0032 // synchronize updates. However, Cordz collection threads may call 'Value()' at
0033 // any point, so the class needs to provide thread safe access.
0034 //
0035 // This class is thread-safe. But as per above comments, all non-const methods
0036 // should be used single-threaded only: updates are thread-safe but lossy.
0037 class CordzUpdateTracker {
0038  public:
0039   // Tracked update methods.
0040   enum MethodIdentifier {
0041     kUnknown,
0042     kAppendCord,
0043     kAppendCordBuffer,
0044     kAppendExternalMemory,
0045     kAppendString,
0046     kAssignCord,
0047     kAssignString,
0048     kClear,
0049     kConstructorCord,
0050     kConstructorString,
0051     kCordReader,
0052     kFlatten,
0053     kGetAppendBuffer,
0054     kGetAppendRegion,
0055     kMakeCordFromExternal,
0056     kMoveAppendCord,
0057     kMoveAssignCord,
0058     kMovePrependCord,
0059     kPrependCord,
0060     kPrependCordBuffer,
0061     kPrependString,
0062     kRemovePrefix,
0063     kRemoveSuffix,
0064     kSetExpectedChecksum,
0065     kSubCord,
0066 
0067     // kNumMethods defines the number of entries: must be the last entry.
0068     kNumMethods,
0069   };
0070 
0071   // Constructs a new instance. All counters are zero-initialized.
0072   constexpr CordzUpdateTracker() noexcept : values_{} {}
0073 
0074   // Copy constructs a new instance.
0075   CordzUpdateTracker(const CordzUpdateTracker& rhs) noexcept { *this = rhs; }
0076 
0077   // Assigns the provided value to this instance.
0078   CordzUpdateTracker& operator=(const CordzUpdateTracker& rhs) noexcept {
0079     for (int i = 0; i < kNumMethods; ++i) {
0080       values_[i].store(rhs.values_[i].load(std::memory_order_relaxed),
0081                        std::memory_order_relaxed);
0082     }
0083     return *this;
0084   }
0085 
0086   // Returns the value for the specified method.
0087   int64_t Value(MethodIdentifier method) const {
0088     return values_[method].load(std::memory_order_relaxed);
0089   }
0090 
0091   // Increases the value for the specified method by `n`
0092   void LossyAdd(MethodIdentifier method, int64_t n = 1) {
0093     auto& value = values_[method];
0094     value.store(value.load(std::memory_order_relaxed) + n,
0095                 std::memory_order_relaxed);
0096   }
0097 
0098   // Adds all the values from `src` to this instance
0099   void LossyAdd(const CordzUpdateTracker& src) {
0100     for (int i = 0; i < kNumMethods; ++i) {
0101       MethodIdentifier method = static_cast<MethodIdentifier>(i);
0102       if (int64_t value = src.Value(method)) {
0103         LossyAdd(method, value);
0104       }
0105     }
0106   }
0107 
0108  private:
0109   // Until C++20 std::atomic is not constexpr default-constructible, so we need
0110   // a wrapper for this class to be constexpr constructible.
0111   class Counter : public std::atomic<int64_t> {
0112    public:
0113     constexpr Counter() noexcept : std::atomic<int64_t>(0) {}
0114   };
0115 
0116   Counter values_[kNumMethods];
0117 };
0118 
0119 }  // namespace cord_internal
0120 ABSL_NAMESPACE_END
0121 }  // namespace absl
0122 
0123 #endif  // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_