]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/histogram/accumulators/count.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / histogram / accumulators / count.hpp
index 2fe1dbfbe80ea9f2ad7e65417cfe868662ca6f58..df947b9679a1075674ad67366f4f1d0908835cb1 100644 (file)
@@ -4,10 +4,11 @@
 // (See accompanying file LICENSE_1_0.txt
 // or copy at http://www.boost.org/LICENSE_1_0.txt)
 
-#ifndef BOOST_HISTOGRAM_ACCUMULATORS_NUMBER_HPP
-#define BOOST_HISTOGRAM_ACCUMULATORS_NUMBER_HPP
+#ifndef BOOST_HISTOGRAM_ACCUMULATORS_COUNT_HPP
+#define BOOST_HISTOGRAM_ACCUMULATORS_COUNT_HPP
 
 #include <boost/core/nvp.hpp>
+#include <boost/histogram/detail/atomic_number.hpp>
 #include <boost/histogram/fwd.hpp> // for count<>
 #include <type_traits>             // for std::common_type
 
@@ -16,32 +17,44 @@ namespace histogram {
 namespace accumulators {
 
 /**
-  Uses a C++ builtin arithmetic type to accumulate a count.
+  Wraps a C++ arithmetic type with optionally thread-safe increments and adds.
 
-  This wrapper class may be used as a base class by users who want to add custom metadata
-  to each bin of a histogram. Otherwise, arithmetic types should be used directly as
-  accumulators in storages for simplicity. In other words, prefer `dense_storage<double>`
-  over `dense_storage<count<double>>`, both are functionally equivalent.
+  This adaptor optionally uses atomic operations to make concurrent increments and
+  additions thread-safe for the stored arithmetic value, which can be integral or
+  floating point. For small histograms, the performance will still be poor because of
+  False Sharing, see https://en.wikipedia.org/wiki/False_sharing for details.
 
-  When weighted data is accumulated and high precision is required, use
-  `accumulators::sum` instead. If a local variance estimate for the weight distribution
-  should be computed as well (generally needed for a detailed statistical analysis), use
-  `accumulators::weighted_sum`.
+  Warning: Assignment is not thread-safe in this implementation, so don't assign
+  concurrently.
+
+  This wrapper class can be used as a base class by users to add arbitrary metadata to
+  each bin of a histogram.
+
+  When weighted samples are accumulated and high precision is required, use
+  `accumulators::sum` instead (at the cost of lower performance). If a local variance
+  estimate for the weight distribution should be computed as well (generally needed for a
+  detailed statistical analysis), use `accumulators::weighted_sum`.
+
+  @tparam T C++ builtin arithmetic type (integer or floating point).
+  @tparam ThreadSafe Set to true to make increments and adds thread-safe.
 */
-template <class ValueType>
+template <class ValueType, bool ThreadSafe>
 class count {
+  using internal_type =
+      std::conditional_t<ThreadSafe, detail::atomic_number<ValueType>, ValueType>;
+
 public:
   using value_type = ValueType;
   using const_reference = const value_type&;
 
-  count() = default;
+  count() noexcept = default;
 
   /// Initialize count to value and allow implicit conversion
-  count(const_reference value) noexcept : value_(value) {}
+  count(const_reference value) noexcept : value_{value} {}
 
   /// Allow implicit conversion from other count
-  template <class T>
-  count(const count<T>& c) noexcept : count(c.value()) {}
+  template <class T, bool B>
+  count(const count<T, B>& c) noexcept : count{c.value()} {}
 
   /// Increment count by one
   count& operator++() noexcept {
@@ -72,16 +85,20 @@ public:
   bool operator!=(const count& rhs) const noexcept { return !operator==(rhs); }
 
   /// Return count
-  const_reference value() const noexcept { return value_; }
+  value_type value() const noexcept { return value_; }
 
   // conversion to value_type must be explicit
   explicit operator value_type() const noexcept { return value_; }
 
   template <class Archive>
   void serialize(Archive& ar, unsigned /* version */) {
-    ar& make_nvp("value", value_);
+    auto v = value();
+    ar& make_nvp("value", v);
+    value_ = v;
   }
 
+  static constexpr bool thread_safe() noexcept { return ThreadSafe; }
+
   // begin: extra operators to make count behave like a regular number
 
   count& operator*=(const count& rhs) noexcept {
@@ -114,10 +131,33 @@ public:
 
   bool operator>=(const count& rhs) const noexcept { return value_ >= rhs.value_; }
 
+  friend bool operator==(const_reference x, const count& rhs) noexcept {
+    return x == rhs.value_;
+  }
+
+  friend bool operator!=(const_reference x, const count& rhs) noexcept {
+    return x != rhs.value_;
+  }
+
+  friend bool operator<(const_reference x, const count& rhs) noexcept {
+    return x < rhs.value_;
+  }
+
+  friend bool operator>(const_reference x, const count& rhs) noexcept {
+    return x > rhs.value_;
+  }
+
+  friend bool operator<=(const_reference x, const count& rhs) noexcept {
+    return x <= rhs.value_;
+  }
+  friend bool operator>=(const_reference x, const count& rhs) noexcept {
+    return x >= rhs.value_;
+  }
+
   // end: extra operators
 
 private:
-  value_type value_{};
+  internal_type value_{};
 };
 
 } // namespace accumulators
@@ -126,10 +166,10 @@ private:
 
 #ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
 namespace std {
-template <class T, class U>
-struct common_type<boost::histogram::accumulators::count<T>,
-                   boost::histogram::accumulators::count<U>> {
-  using type = boost::histogram::accumulators::count<common_type_t<T, U>>;
+template <class T, class U, bool B1, bool B2>
+struct common_type<boost::histogram::accumulators::count<T, B1>,
+                   boost::histogram::accumulators::count<U, B2>> {
+  using type = boost::histogram::accumulators::count<common_type_t<T, U>, (B1 || B2)>;
 };
 } // namespace std
 #endif