Make metrics thread-safe
Some checks failed
Tests / Clang total: 1533, failed: 1, passed: 1532
Tests / Clang - debug total: 1531, passed: 1531
Tests / SIMD fallback total: 1533, failed: 1, passed: 1532
Tests / Release [gcc] total: 1533, failed: 1, passed: 1532
Tests / Release [gcc,aarch64] total: 1144, failed: 2, passed: 1142
Tests / Coverage total: 1151, passed: 1151
weaselab/conflict-set/pipeline/head There was a failure building this commit

Even concurrently with calling non-const methods on the associated
ConflictSet
This commit is contained in:
2024-07-12 13:22:02 -07:00
parent ef14003781
commit 3288c583e4
10 changed files with 111 additions and 22 deletions

View File

@@ -551,7 +551,7 @@ struct Metric {
const char *name;
const char *help;
ConflictSet::MetricsV1::Type type;
double value;
std::atomic<double> value;
protected:
Metric(ConflictSet::Impl *impl, const char *name, const char *help,
@@ -562,15 +562,27 @@ struct Gauge : private Metric {
Gauge(ConflictSet::Impl *impl, const char *name, const char *help)
: Metric(impl, name, help, ConflictSet::MetricsV1::Gauge) {}
void set(double value) { this->value = value; }
void set(double value) {
this->value.store(value, std::memory_order_relaxed);
}
};
struct Counter : private Metric {
Counter(ConflictSet::Impl *impl, const char *name, const char *help)
: Metric(impl, name, help, ConflictSet::MetricsV1::Counter) {}
// Expensive. Accumulate locally and then call add instead of repeatedly
// calling add.
void add(double value) {
assert(value >= 0);
this->value += value;
static_assert(std::atomic<double>::is_always_lock_free);
double old = this->value.load(std::memory_order_relaxed);
for (;;) {
double newVal = old + value;
if (this->value.compare_exchange_weak(old, newVal,
std::memory_order_relaxed)) {
break;
}
}
}
};
@@ -3235,7 +3247,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
++i, m = m->prev) {
metrics[i].name = m->name;
metrics[i].help = m->help;
metrics[i].value = &m->value;
metrics[i].p = m;
metrics[i].type = m->type;
}
std::sort(metrics, metrics + metricsCount,
@@ -3274,6 +3286,11 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
// ==================== END METRICS DEFINITIONS ====================
#undef GAUGE
#undef COUNTER
void getMetricsV1(MetricsV1 **metrics, int *count) {
*metrics = this->metrics;
*count = metricsCount;
}
};
Metric::Metric(ConflictSet::Impl *impl, const char *name, const char *help,
@@ -3414,8 +3431,11 @@ int64_t internal_getBytes(ConflictSet::Impl *impl) { return impl->getBytes(); }
void internal_getMetricsV1(ConflictSet::Impl *impl,
ConflictSet::MetricsV1 **metrics, int *count) {
*metrics = impl->metrics;
*count = impl->metricsCount;
impl->getMetricsV1(metrics, count);
}
double internal_getMetricValue(const ConflictSet::MetricsV1 *metric) {
return ((Metric *)metric->p)->value.load(std::memory_order_relaxed);
}
// ==================== END IMPLEMENTATION ====================
@@ -3506,6 +3526,10 @@ void ConflictSet::getMetricsV1(MetricsV1 **metrics, int *count) const {
return internal_getMetricsV1(impl, metrics, count);
}
double ConflictSet::MetricsV1::getValue() const {
return internal_getMetricValue(this);
}
ConflictSet::ConflictSet(int64_t oldestVersion)
: impl(internal_create(oldestVersion)) {}