This is an automated email from the ASF dual-hosted git repository.

chenBright pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new 6ab8c0e3 Fix Maxer default value for floating-point types (#3563)
6ab8c0e3 is described below

commit 6ab8c0e3777249d7569b7275bac185ecf488f80a
Author: Bright Chen <[email protected]>
AuthorDate: Wed Sep 23 18:56:01 2026 +0800

    Fix Maxer default value for floating-point types (#3563)
---
 src/bvar/reducer.h             | 22 ++++++++++++++++------
 test/bvar_reducer_unittest.cpp |  7 +++++++
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/bvar/reducer.h b/src/bvar/reducer.h
index 8b40fe3f..c49d1e4c 100644
--- a/src/bvar/reducer.h
+++ b/src/bvar/reducer.h
@@ -78,6 +78,15 @@ template <typename T>
 using EnableIfBabylonCounter =
     std::enable_if_t<IsBabylonCounterSupported<T>::value>;
 
+// babylon::GenericsConcurrentMaxer initializes its aggregation value with
+// numeric_limits<T>::min(). For floating-point types this is the smallest
+// positive normalized value, so an aggregation containing only negative values
+// is treated as empty. Keep floating-point Maxer instances on the generic
+// implementation until babylon fixes its aggregation identity.
+template <typename T>
+using EnableIfBabylonMaxerCounter = std::enable_if_t<
+    IsBabylonCounterSupported<T>::value && std::is_integral<T>::value>;
+
 template<typename T, typename Counter, typename Op, typename InvOp>
 class BabylonVariable: public Variable {
 public:
@@ -442,13 +451,13 @@ public:
     typedef T value_type;
     typedef typename Base::sampler_type sampler_type;
 
-    Maxer() : Base(std::numeric_limits<T>::min()) {}
+    Maxer() : Base(std::numeric_limits<T>::lowest()) {}
     Maxer(const butil::StringPiece& name)
-        : Base(std::numeric_limits<T>::min()) {
+        : Base(std::numeric_limits<T>::lowest()) {
         this->expose(name);
     }
     Maxer(const butil::StringPiece& prefix, const butil::StringPiece& name)
-        : Base(std::numeric_limits<T>::min()) {
+        : Base(std::numeric_limits<T>::lowest()) {
         this->expose_as(prefix, name);
     }
     ~Maxer() override { Variable::hide(); }
@@ -485,13 +494,14 @@ public:
         return std::max(result, _default_value);
     }
 private:
-    T _default_value{std::numeric_limits<T>::min()};
+    T _default_value{std::numeric_limits<T>::lowest()};
 };
 } // namespace detail
 
-// Numerical types supported by babylon counter.
+// Integral types supported by babylon counter. Floating-point Maxer uses the
+// generic implementation because babylon's aggregation identity is incorrect.
 template <typename T>
-class Maxer<T, detail::EnableIfBabylonCounter<T>>
+class Maxer<T, detail::EnableIfBabylonMaxerCounter<T>>
     : public detail::BabylonVariable<T, detail::ConcurrentMaxer<T>,
                                      detail::MaxTo<T>, detail::VoidOp> {
 public:
diff --git a/test/bvar_reducer_unittest.cpp b/test/bvar_reducer_unittest.cpp
index f905e110..e001246a 100644
--- a/test/bvar_reducer_unittest.cpp
+++ b/test/bvar_reducer_unittest.cpp
@@ -182,6 +182,11 @@ TEST_F(ReducerTest, max) {
     ASSERT_EQ(30, reducer2.get_value());
     reducer2 << std::numeric_limits<int>::max();
     ASSERT_EQ(std::numeric_limits<int>::max(), reducer2.get_value());
+
+    bvar::Maxer<double> reducer3;
+    ASSERT_EQ(std::numeric_limits<double>::lowest(), reducer3.get_value());
+    reducer3 << -30.5 << -10.5 << -20.5;
+    ASSERT_EQ(-10.5, reducer3.get_value());
 }
 
 bvar::Adder<long> g_a;
@@ -300,6 +305,8 @@ TEST_F(ReducerTest, babylon_counter_backend) {
                   "Adder<double> should be backed by a babylon counter");
     static_assert(IsBabylonBacked<bvar::Maxer<int64_t> >::value,
                   "Maxer<int64_t> should be backed by a babylon counter");
+    static_assert(!IsBabylonBacked<bvar::Maxer<double> >::value,
+                  "Maxer<double> should use the generic implementation");
     static_assert(IsBabylonBacked<bvar::Miner<int64_t> >::value,
                   "Miner<int64_t> should be backed by a babylon counter");
     // babylon counters only support arithmetic types not larger than 8 bytes.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to