[metrics] Add MetricsAccumulator

MetricsAccumulator metrics are a generalization of counters that allow
a custom function to be supplied that specifies how to combine
incoming values. This allows for the definition of things like minimum
and maximum metrics.

Test: libartbase_gtests
Bug: 170149255
Change-Id: Ibc928a5d0e5cad3036e5829be9a535bc4a685ae1
diff --git a/libartbase/base/metrics/metrics_test.cc b/libartbase/base/metrics/metrics_test.cc
index 7b26e43..eae9367 100644
--- a/libartbase/base/metrics/metrics_test.cc
+++ b/libartbase/base/metrics/metrics_test.cc
@@ -90,6 +90,26 @@
   EXPECT_GT(CounterValue(test_counter), 0u);
 }
 
+TEST_F(MetricsTest, AccumulatorMetric) {
+  MetricsAccumulator<DatumId::kClassLoadingTotalTime, uint64_t, std::max> accumulator;
+
+  std::vector<std::thread> threads;
+
+  constexpr uint64_t kMaxValue = 100;
+
+  for (uint64_t i = 0; i <= kMaxValue; i++) {
+    threads.emplace_back(std::thread{[&accumulator, i]() {
+      accumulator.Add(i);
+    }});
+  }
+
+  for (auto& thread : threads) {
+    thread.join();
+  }
+
+  EXPECT_EQ(CounterValue(accumulator), kMaxValue);
+}
+
 TEST_F(MetricsTest, DatumName) {
   EXPECT_EQ("ClassVerificationTotalTime", DatumName(DatumId::kClassVerificationTotalTime));
 }