struct stat_bucket {
struct stat_series *parent;
atomic_size_t count;
atomic_size_t sum;
void *private;
};
struct stat_series {
stat_series_callback bucket_reset;
struct stat_bucket *buckets;
uint32_t nbuckets;
_Atomic uint32_t current;
time_t bucket_us;
_Atomic uint64_t last_update_us;
void *private;
struct spinlock lock;
};
typedef size_t (*stat_series_callback)(struct stat_bucket * bucket);
struct stat_series * stat_series_create(uint32_t nbuckets, time_t bucket_us, stat_series_callback bucket_reset, void *private);
void stat_series_init(struct stat_series *s, struct stat_bucket *buckets, uint32_t nbuckets, time_t bucket_us, stat_series_callback bucket_reset, void *private);
void stat_series_reset(struct stat_series *s);
void stat_series_record(struct stat_series *s, size_t value, stat_series_callback callback);
void stat_series_advance(struct stat_series *s, time_t now_us);
#define stat_series_for_each(series, iter) \
for (uint32_t __i = 0; \
(iter = &((series)->buckets[__i]), __i < (series)->nbuckets); __i++)
#define STAT_SERIES_DEFINE(name, n, bucket_us) \
static struct stat_bucket name##_buckets[(n)] = {0}; \
static struct stat_series name = { \
.buckets = name##_buckets, \
.nbuckets = (n), \
.bucket_us = (bucket_us), \
};
#define STAT_SERIES_CUR_BUCKET(s) (&(s)->buckets[(s)->current])