Index: base/metrics/histogram_macros_internal.h |
diff --git a/base/metrics/histogram_macros_internal.h b/base/metrics/histogram_macros_internal.h |
index 53e4f11b75d6dcce1fa9ea38817cf481eb8e5a2f..c107a4729d26243d6e81d510e03fb769abb137aa 100644 |
--- a/base/metrics/histogram_macros_internal.h |
+++ b/base/metrics/histogram_macros_internal.h |
@@ -5,6 +5,11 @@ |
#ifndef BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_ |
#define BASE_METRICS_HISTOGRAM_MACROS_INTERNAL_H_ |
+#include <stdint.h> |
+ |
+#include <limits> |
+#include <type_traits> |
+ |
#include "base/atomicops.h" |
#include "base/logging.h" |
#include "base/metrics/histogram.h" |
@@ -96,17 +101,42 @@ |
base::Histogram::FactoryGet(name, min, max, bucket_count, flag)) |
// This is a helper macro used by other macros and shouldn't be used directly. |
-// For an enumeration with N items, recording values in the range [0, N - 1], |
-// this macro creates a linear histogram with N + 1 buckets: |
-// [0, 1), [1, 2), ..., [N - 1, N), and an overflow bucket [N, infinity). |
+// The bucketing scheme is linear with a bucket size of 1. For N items, |
+// recording values in the range [0, N - 1] creates a linear histogram with N + |
+// 1 buckets: |
+// [0, 1), [1, 2), ..., [N - 1, N) |
+// and an overflow bucket [N, infinity). |
+// |
// Code should never emit to the overflow bucket; only to the other N buckets. |
-// This allows future versions of Chrome to safely append new entries to the |
-// enumeration. Otherwise, the histogram would have [N - 1, infinity) as its |
-// overflow bucket, and so the maximal value (N - 1) would be emitted to this |
-// overflow bucket. But, if an additional enumerated value were later added, the |
-// bucket label for the value (N - 1) would change to [N - 1, N), which would |
-// result in different versions of Chrome using different bucket labels for |
-// identical data. |
+// This allows future versions of Chrome to safely increase the boundary size. |
+// Otherwise, the histogram would have [N - 1, infinity) as its overflow bucket, |
+// and so the maximal value (N - 1) would be emitted to this overflow bucket. |
+// But, if an additional value were later added, the bucket label for |
+// the value (N - 1) would change to [N - 1, N), which would result in different |
+// versions of Chrome using different bucket labels for identical data. |
+#define INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG(name, sample, boundary, \ |
+ flag) \ |
+ do { \ |
+ static_assert(!std::is_enum<decltype(sample)>::value, \ |
+ "|sample| should not be an enum type!"); \ |
+ static_assert(!std::is_enum<decltype(boundary)>::value, \ |
+ "|boundary| should not be an enum type!"); \ |
+ STATIC_HISTOGRAM_POINTER_BLOCK( \ |
+ name, Add(sample), \ |
+ base::LinearHistogram::FactoryGet(name, 1, boundary, boundary + 1, \ |
+ flag)); \ |
+ } while (0) |
+ |
+// Similar to the previous macro but intended for enumerations. This delegates |
+// the work to the previous macro, but supports scoped enumerations as well by |
+// forcing an explicit cast to the HistogramBase::Sample integral type. |
+// |
+// Note the range checks verify two separate issues: |
+// - that the declared enum max isn't out of range of HistogramBase::Sample |
+// - that the declared enum max is > 0 |
+// |
+// TODO(dcheng): This should assert that the passed in types are actually enum |
+// types. |
#define INTERNAL_HISTOGRAM_ENUMERATION_WITH_FLAG(name, sample, boundary, flag) \ |
do { \ |
static_assert( \ |
@@ -115,9 +145,14 @@ |
std::is_same<std::remove_const<decltype(sample)>::type, \ |
std::remove_const<decltype(boundary)>::type>::value, \ |
"|sample| and |boundary| shouldn't be of different enums"); \ |
- STATIC_HISTOGRAM_POINTER_BLOCK( \ |
- name, Add(sample), base::LinearHistogram::FactoryGet( \ |
- name, 1, boundary, boundary + 1, flag)); \ |
+ static_assert( \ |
+ static_cast<uintmax_t>(boundary) < \ |
+ static_cast<uintmax_t>( \ |
+ std::numeric_limits<base::HistogramBase::Sample>::max()), \ |
+ "|boundary| is out of range of HistogramBase::Sample"); \ |
+ INTERNAL_HISTOGRAM_EXACT_LINEAR_WITH_FLAG( \ |
+ name, static_cast<base::HistogramBase::Sample>(sample), \ |
+ static_cast<base::HistogramBase::Sample>(boundary), flag); \ |
} while (0) |
// This is a helper macro used by other macros and shouldn't be used directly. |