#pragma once #include "ConflictSet.h" #include "Internal.h" #include #include #include struct Metric { Metric *prev; const char *name; const char *help; weaselab::ConflictSet::MetricsV1::Type type; std::atomic value; protected: Metric(Metric *&metricList, int &metricsCount, const char *name, const char *help, weaselab::ConflictSet::MetricsV1::Type type) : prev(std::exchange(metricList, this)), name(name), help(help), type(type), value(0) { ++metricsCount; } }; struct Gauge : private Metric { Gauge(Metric *&metricList, int &metricsCount, const char *name, const char *help) : Metric(metricList, metricsCount, name, help, weaselab::ConflictSet::MetricsV1::Gauge) {} void set(int64_t value) { this->value.store(value, std::memory_order_relaxed); } }; struct Counter : private Metric { Counter(Metric *&metricList, int &metricsCount, const char *name, const char *help) : Metric(metricList, metricsCount, name, help, weaselab::ConflictSet::MetricsV1::Counter) {} // Expensive. Accumulate locally and then call add instead of repeatedly // calling add. void add(int64_t value) { assert(value >= 0); static_assert(std::atomic::is_always_lock_free); this->value.fetch_add(value, std::memory_order_relaxed); } }; inline weaselab::ConflictSet::MetricsV1 *initMetrics(Metric *metricsList, int metricsCount) { weaselab::ConflictSet::MetricsV1 *metrics = (weaselab::ConflictSet::MetricsV1 *)safe_malloc(metricsCount * sizeof(metrics[0])); for (auto [i, m] = std::make_tuple(metricsCount - 1, metricsList); i >= 0; --i, m = m->prev) { metrics[i].name = m->name; metrics[i].help = m->help; metrics[i].p = m; metrics[i].type = m->type; } return metrics; }