glean/interprocess/cpp/counters.cpp (88 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 "common/hs/util/cpp/wrap.h" #include "glean/interprocess/cpp/counters.h" #include "glean/interprocess/cpp/counters_ffi.h" #include <fstream> #include <unordered_map> #include <boost/interprocess/file_mapping.hpp> #include <boost/interprocess/mapped_region.hpp> using namespace facebook::hs; extern "C" { struct glean_interprocess_counters_t final : public facebook::glean::interprocess::Counters{ boost::interprocess::file_mapping mapping; boost::interprocess::mapped_region region; std::atomic<uint64_t> *counters; size_t size; explicit glean_interprocess_counters_t(const char *path, size_t n) { mapping = boost::interprocess::file_mapping( path, boost::interprocess::read_write); region = boost::interprocess::mapped_region( mapping, boost::interprocess::read_write, 0, n * sizeof(uint64_t)); counters = static_cast<std::atomic<uint64_t> *>(region.get_address()); size = n; assert(std::atomic_is_lock_free(counters)); } static void create( const char *path, size_t n) { std::vector<uint64_t> contents(n, 0); std::ofstream stream(path, std::ios::out | std::ios::binary); stream.write( reinterpret_cast<const char *>(contents.data()), n * sizeof(uint64_t)); } std::atomic<uint64_t> *counter(size_t i) override { if (i >= size) { throw std::invalid_argument("counter index out of range"); } return counters + i; } }; const char *glean_interprocess_counters_create(const char *path, size_t size) { return ffi::wrap([=] { glean_interprocess_counters_t::create(path, size); }); } const char *glean_interprocess_counters_open( const char *path, size_t size, glean_interprocess_counters_t **counters) { return ffi::wrap([=] { *counters = new glean_interprocess_counters_t(path, size); }); } void glean_interprocess_counters_close( glean_interprocess_counters_t *counters) { ffi::free_(counters); } const char *glean_interprocess_counters_set( glean_interprocess_counters_t *counters, size_t index, uint64_t value) { return ffi::wrap([=] { counters->counter(index)->store(value); }); } const char *glean_interprocess_counters_get( glean_interprocess_counters_t *counters, size_t index, uint64_t *value) { return ffi::wrap([=] { *value = counters->counter(index)->load(); }); } } namespace facebook { namespace glean { namespace interprocess { void countersSetup(const std::string& path, size_t size) { glean_interprocess_counters_t::create(path.c_str(), size); } std::unique_ptr<Counters> counters(const std::string& path, size_t size) { return std::make_unique<glean_interprocess_counters_t>(path.c_str(), size); } } } }