blob: b4a0fff599282c2d9a090b05db2bbf9329cf90c1 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <unistd.h>
#include <atomic>
#include <cstdint>
#include <type_traits>
#include <cobalt-client/cpp/metric_options.h>
#include <cobalt-client/cpp/types_internal.h>
namespace cobalt_client {
namespace internal {
// Note: Everything on this namespace is internal, no external users should rely
// on the behaviour of any of these classes.
// BaseCounter and RemoteCounter differ in that the first is simply a thin wrapper over
// an atomic while the second provides Cobalt Fidl specific API and holds more metric related
// data for a full fledged metric.
// Thin wrapper on top of an atomic, which provides a fixed memory ordering for all calls.
// Calls are inlined to reduce overhead.A
template <typename T>
class BaseCounter {
// Alias for the underlying counter type.
using Type = T;
// All atomic operations use this memory order.
static constexpr auto kMemoryOrder = std::memory_order_relaxed;
BaseCounter() : counter_(0) {}
BaseCounter(const BaseCounter&) = delete;
BaseCounter(BaseCounter&& other) noexcept : counter_(other.Exchange(0)) {}
BaseCounter& operator=(const BaseCounter&) = delete;
BaseCounter& operator=(BaseCounter&&) = delete;
~BaseCounter() = default;
// Increments |counter_| by |val|.
void Increment(Type val = 1) { counter_.fetch_add(val, kMemoryOrder); }
// Returns the current value of|counter_| and resets it to |val|.
Type Exchange(Type val = 0) { return, kMemoryOrder); }
// Returns the current value of |counter_|.
Type Load() const { return counter_.load(kMemoryOrder); }
static_assert(std::is_integral<Type>::value, "Can only count integral types");
std::atomic<Type> counter_;
// Counter which represents a standalone cobalt metric. Provides API for converting
// to cobalt FIDL types.
// This class is moveable and move-assignable.
// This class is not copy or copy-assignable.
// This class is thread-safe except for |Flushing| which is thread-compatible.
class RemoteCounter : public BaseCounter<int64_t>, public FlushInterface {
RemoteCounter() = default;
explicit RemoteCounter(const MetricOptions& metric_options);
RemoteCounter(const RemoteCounter&) = delete;
RemoteCounter(RemoteCounter&&) noexcept;
RemoteCounter& operator=(const RemoteCounter&) = delete;
RemoteCounter& operator=(RemoteCounter&&) = delete;
~RemoteCounter() override = default;
bool Flush(Logger* logger) override;
void UndoFlush() override;
// Returns the metric_id associated with this remote metric.
const MetricOptions& metric_options() const { return metric_options_; }
int64_t buffer_;
MetricOptions metric_options_;
} // namespace internal
} // namespace cobalt_client