4 #ifndef _UTIL_SLIDING_COUNTER_H     5 #define _UTIL_SLIDING_COUNTER_H    10 #include "base/atomic_wrapper.h"    11 #include "base/integral_types.h"    12 #include "base/logging.h"    18   static void SetCurrentTime_Test(uint32 time);
    23   static uint32 CurrentTime();
    25   mutable base::atomic_wrapper<uint32> last_ts_;
    32   mutable base::atomic_wrapper<T> count_[NUM];
    37   int32 MoveTsIfNeeded() 
const;
    40   static constexpr 
unsigned SIZE = NUM;
    41   static constexpr 
unsigned SPAN = PRECISION*NUM;
    44     static_assert(NUM > 1, 
"Invalid window size");
    48   void Inc() { IncBy(1); }
    50   T IncBy(int32 delta) {
    51     int32 bin = MoveTsIfNeeded();
    52     T tmp = count_[bin].fetch_add(delta, std::memory_order_acq_rel);
    59   T DecIfNotLess(int32 delta) {
    60     int32 bin = MoveTsIfNeeded();
    63       val = count_[bin].load(std::memory_order_acquire);
    67     } 
while(!count_[bin].compare_exchange_weak(val, val - delta,  std::memory_order_acq_rel));
    73   T SumLast(
unsigned offset, 
unsigned count = 
unsigned(-1)) 
const;
    78     for (
unsigned i = 0; i < NUM; ++i)
    79       sum += count_[i].load(std::memory_order_acquire);
    84     for (
unsigned i = 0; i < NUM; ++i)
    85       count_[i].store(0, std::memory_order_release);
    88   uint32 last_ts()
 const { 
return last_ts_; }
    89   static unsigned span() { 
return SPAN; }
    90   static unsigned bin_span() {
return PRECISION; }
   101   static constexpr 
unsigned kNum = 10;
   102   static constexpr 
unsigned kPrecision = 1;
   108   void Reset() { window_.Reset(); }
   123 template<
typename T, 
unsigned NUM, 
unsigned PRECISION>
   125   uint32 current_time = CurrentTime() / PRECISION;
   126   uint32 last_ts = last_ts_.load(std::memory_order_acquire);
   127   if (last_ts >= current_time) {
   130     return last_ts % NUM;
   132   if (last_ts + NUM <= current_time) {
   134     for (uint32 i = 0; i < NUM; ++i) {
   135       count_[i].store(0, std::memory_order_release);
   139     for (uint32 i = last_ts + 1; i <= current_time; ++i) {
   140       count_[i % NUM].store(0, std::memory_order_release);
   143   if (last_ts_.compare_exchange_strong(last_ts, current_time, std::memory_order_acq_rel)) {
   144     return current_time % NUM;
   146   return last_ts % NUM;
   149 template<
typename T, 
unsigned NUM, 
unsigned PRECISION>
   150 T SlidingSecondCounterT<T, NUM, PRECISION>::SumLast(
unsigned offset, 
unsigned count)
 const {
   151   if (count > NUM - offset) {
   152     count = NUM - offset;
   155   int32 start = MoveTsIfNeeded() - offset - count + 1;
   156   if (start < 0) start += NUM;
   157   for (
unsigned i = 0; i < count; ++i) {
   158     sum += count_[ (start + i) % NUM ].load(std::memory_order_acquire);
   165 #endif  // _UTIL_SLIDING_COUNTER_H