#ifndef ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_
#define ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_
#include <stdint.h>
#include <atomic>
#include "absl/base/optimization.h"
#include "absl/profiling/internal/exponential_biased.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace profiling_internal {
class PeriodicSamplerBase {
public:
PeriodicSamplerBase() = default;
PeriodicSamplerBase(PeriodicSamplerBase&&) = default;
PeriodicSamplerBase(const PeriodicSamplerBase&) = default;
inline bool Sample() noexcept;
inline bool SubtleMaybeSample() noexcept;
bool SubtleConfirmSample() noexcept;
protected:
~PeriodicSamplerBase() = default;
virtual int64_t GetExponentialBiased(int period) noexcept;
private:
virtual int period() const noexcept = 0;
uint64_t stride_ = 0;
absl::profiling_internal::ExponentialBiased rng_;
};
inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {
if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) {
return false;
}
return true;
}
inline bool PeriodicSamplerBase::Sample() noexcept {
return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample()
: false;
}
template <typename Tag, int default_period = 0>
class PeriodicSampler final : public PeriodicSamplerBase {
public:
~PeriodicSampler() = default;
int period() const noexcept final {
return period_.load(std::memory_order_relaxed);
}
static void SetGlobalPeriod(int period) {
period_.store(period, std::memory_order_relaxed);
}
private:
static std::atomic<int> period_;
};
template <typename Tag, int default_period>
std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);
} ABSL_NAMESPACE_END
}
#endif