text: // Copyright (c) 2015, Baidu.com, Inc. All Rights Reserved
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef TERA_COMMON_COUNTER_H_
  #define TERA_COMMON_COUNTER_H_
  
  #include <stdio.h>
  
  #include "common/atomic.h"
  #include "common/timer.h"
  
  namespace tera {
  
  class Counter {
   public:
    Counter() : val_(0) {}
    int64_t Add(int64_t v) { return atomic_add64(&val_, v) + v; }
    int64_t Sub(int64_t v) { return atomic_add64(&val_, -v) - v; }
    int64_t Inc() { return atomic_add64(&val_, 1) + 1; }
    int64_t Dec() { return atomic_add64(&val_, -1) - 1; }
    int64_t Get() const { return val_; }
    int64_t Set(int64_t v) { return atomic_swap64(&val_, v); }
    int64_t Clear() { return atomic_swap64(&val_, 0); }
  
   private:
    volatile int64_t val_;
  };
  
  class AutoCounter {
   public:
    AutoCounter(Counter* counter, const char* msg1, const char* msg2 = NULL)
        : counter_(counter), msg1_(msg1), msg2_(msg2) {
      start_ = get_micros();
    }
    ~AutoCounter() {
      int64_t end = get_micros();
      if (end - start_ > 5000000) {
        counter_->Inc();
        int64_t t = (end - start_) / 1000000;
        if (!msg2_) {
          fprintf(stderr, "%s [AutoCounter] %s hang for %ld s\n", get_curtime_str().data(), msg1_, t);
        } else {
          fprintf(stderr, "%s [AutoCounter] %s %s hang for %ld s\n", get_curtime_str().data(), msg1_,
                  msg2_, t);
        }
      }
    }
  
   private:
    Counter* counter_;
    int64_t start_;
    const char* msg1_;
    const char* msg2_;
  };
  }  // namespace common
  
  #endif  // TERA_COMMON_COUNTER_H_
  