1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #pragma once 6 7 #include <atomic> 8 #include <stdint.h> 9 #include <unistd.h> 10 11 #include <cobalt-client/cpp/metric-options.h> 12 #include <cobalt-client/cpp/types-internal.h> 13 #include <fbl/function.h> 14 #include <fbl/string.h> 15 #include <fbl/vector.h> 16 17 namespace cobalt_client { 18 namespace internal { 19 // Note: Everything on this namespace is internal, no external users should rely 20 // on the behaviour of any of these classes. 21 22 // BaseCounter and RemoteCounter differ in that the first is simply a thin wrapper over 23 // an atomic while the second provides Cobalt Fidl specific API and holds more metric related 24 // data for a full fledged metric. 25 // 26 // Thin wrapper on top of an atomic, which provides a fixed memory ordering for all calls. 27 // Calls are inlined to reduce overhead.A 28 template <typename T> 29 class BaseCounter { 30 public: 31 // Alias for the underlying counter type. 32 using Type = T; 33 34 // All atomic operations use this memory order. 35 static constexpr auto kMemoryOrder = std::memory_order_relaxed; 36 BaseCounter()37 BaseCounter() 38 : counter_(0) {} 39 BaseCounter(const BaseCounter&) = delete; BaseCounter(BaseCounter && other)40 BaseCounter(BaseCounter&& other) 41 : counter_(other.Exchange(0)) {} 42 BaseCounter& operator=(const BaseCounter&) = delete; 43 BaseCounter& operator=(BaseCounter&&) = delete; 44 ~BaseCounter() = default; 45 46 // Increments |counter_| by |val|. 47 void Increment(Type val = 1) { counter_.fetch_add(val, kMemoryOrder); } 48 49 // Returns the current value of|counter_| and resets it to |val|. 50 Type Exchange(Type val = 0) { return counter_.exchange(val, kMemoryOrder); } 51 52 // Returns the current value of |counter_|. Load()53 Type Load() const { return counter_.load(kMemoryOrder); } 54 55 protected: 56 static_assert(fbl::is_integral<Type>::value, "Can only count integral types"); 57 58 std::atomic<Type> counter_; 59 }; 60 61 // Counter which represents a standalone cobalt metric. Provides API for converting 62 // to cobalt FIDL types. 63 // 64 // This class is moveable and move-assignable. 65 // This class is not copy or copy-assignable. 66 // This class is thread-safe except for |Flushing| which is thread-compatible. 67 class RemoteCounter : public BaseCounter<int64_t>, public FlushInterface { 68 public: 69 RemoteCounter() = default; 70 RemoteCounter(const RemoteMetricInfo& metric_info); 71 RemoteCounter(const RemoteCounter&) = delete; 72 RemoteCounter(RemoteCounter&&); 73 RemoteCounter& operator=(const RemoteCounter&) = delete; 74 RemoteCounter& operator=(RemoteCounter&&) = delete; 75 virtual ~RemoteCounter() = default; 76 77 bool Flush(Logger* logger) override; 78 79 void UndoFlush() override; 80 81 // Should only be called when default constructed. 82 void Initialize(const MetricOptions& metric_options); 83 84 // Returns the metric_id associated with this remote metric. metric_info()85 const RemoteMetricInfo& metric_info() const { return metric_info_; } 86 87 private: 88 int64_t buffer_; 89 // Unique-Id representing this metric in the backend. 90 RemoteMetricInfo metric_info_; 91 }; 92 93 } // namespace internal 94 } // namespace cobalt_client 95