glean/rocksdb/stats.cpp (46 lines of code) (raw):

/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ #include "glean/rocksdb/stats.h" #include <folly/synchronization/Hazptr.h> namespace facebook { namespace glean { namespace rocks { struct AtomicPredicateStats::Impl { // This needs to be protected by a hazard poiter for access. We support reads // concurrent to a write but not concurrent writes and a write replaces the // entire object so a hazptr is sufficient. struct Holder : folly::hazptr_obj_base<Holder> { PredicateStats stats; explicit Holder(PredicateStats s) : stats(std::move(s)) {} }; std::atomic<Holder *> holder = new Holder({}); // We have a separate cohort for each DB - the stats objects we create // are local to the DB so they should be destroyed when the DB object is // destroyed at the latest. folly::hazptr_obj_cohort<> cohort; }; AtomicPredicateStats::AtomicPredicateStats() : impl(std::make_unique<Impl>()) {} AtomicPredicateStats::~AtomicPredicateStats() { delete impl->holder.load(); } void AtomicPredicateStats::set(PredicateStats stats) { auto p = new Impl::Holder(std::move(stats)); p->set_cohort_tag(&impl->cohort); p = impl->holder.exchange(p); if (p) { p->retire(); } } const PredicateStats& AtomicPredicateStats::unprotected() const { return impl->holder.load()->stats; } PredicateStats AtomicPredicateStats::get() const { folly::hazptr_local<1> hptr; return hptr[0].protect(impl->holder)->stats; } size_t AtomicPredicateStats::count(rts::Pid pid) const { folly::hazptr_local<1> hptr; if (auto stat = hptr[0].protect(impl->holder)->stats.get(pid)) { return stat->count; } else { return {}; } } } } }