conditions.cc (2761B)
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 #include "absl/log/internal/conditions.h" 16 17 #include <atomic> 18 #include <cstdint> 19 20 #include "absl/base/config.h" 21 #include "absl/base/internal/cycleclock.h" 22 23 namespace absl { 24 ABSL_NAMESPACE_BEGIN 25 namespace log_internal { 26 namespace { 27 28 // The following code behaves like AtomicStatsCounter::LossyAdd() for 29 // speed since it is fine to lose occasional updates. 30 // Returns old value of *counter. 31 uint32_t LossyIncrement(std::atomic<uint32_t>* counter) { 32 const uint32_t value = counter->load(std::memory_order_relaxed); 33 counter->store(value + 1, std::memory_order_relaxed); 34 return value; 35 } 36 37 } // namespace 38 39 bool LogEveryNState::ShouldLog(int n) { 40 return n > 0 && (LossyIncrement(&counter_) % static_cast<uint32_t>(n)) == 0; 41 } 42 43 bool LogFirstNState::ShouldLog(int n) { 44 const uint32_t counter_value = counter_.load(std::memory_order_relaxed); 45 if (static_cast<int64_t>(counter_value) < n) { 46 counter_.store(counter_value + 1, std::memory_order_relaxed); 47 return true; 48 } 49 return false; 50 } 51 52 bool LogEveryPow2State::ShouldLog() { 53 const uint32_t new_value = LossyIncrement(&counter_) + 1; 54 return (new_value & (new_value - 1)) == 0; 55 } 56 57 bool LogEveryNSecState::ShouldLog(double seconds) { 58 using absl::base_internal::CycleClock; 59 LossyIncrement(&counter_); 60 const int64_t now_cycles = CycleClock::Now(); 61 int64_t next_cycles = next_log_time_cycles_.load(std::memory_order_relaxed); 62 #if defined(__myriad2__) 63 // myriad2 does not have 8-byte compare and exchange. Use a racy version that 64 // is "good enough" but will over-log in the face of concurrent logging. 65 if (now_cycles > next_cycles) { 66 next_log_time_cycles_.store( 67 static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()), 68 std::memory_order_relaxed); 69 return true; 70 } 71 return false; 72 #else 73 do { 74 if (now_cycles <= next_cycles) return false; 75 } while (!next_log_time_cycles_.compare_exchange_weak( 76 next_cycles, 77 static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()), 78 std::memory_order_relaxed, std::memory_order_relaxed)); 79 return true; 80 #endif 81 } 82 83 } // namespace log_internal 84 ABSL_NAMESPACE_END 85 } // namespace absl