Coverage Report

Created: 2025-11-24 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/bvar/reducer.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
// Date 2014/09/24 16:01:08
19
20
#ifndef  BVAR_REDUCER_H
21
#define  BVAR_REDUCER_H
22
23
#include <limits>                                 // std::numeric_limits
24
#include "butil/logging.h"                         // LOG()
25
#include "butil/type_traits.h"                     // butil::add_cr_non_integral
26
#include "butil/class_name.h"                      // class_name_str
27
#include "bvar/variable.h"                        // Variable
28
#include "bvar/detail/combiner.h"                 // detail::AgentCombiner
29
#include "bvar/detail/sampler.h"                  // ReducerSampler
30
#include "bvar/detail/series.h"
31
#include "bvar/window.h"
32
#if WITH_BABYLON_COUNTER
33
#include "babylon/concurrent/counter.h"
34
#endif // WITH_BABYLON_COUNTER
35
36
namespace bvar {
37
38
namespace detail {
39
template<typename O, typename T, typename Op>
40
class SeriesSamplerImpl : public Sampler {
41
public:
42
    SeriesSamplerImpl(O* owner, const Op& op)
43
0
        : _owner(owner), _series(op) {}
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>, bvar::Collected*, bvar::CombineCollected>::SeriesSamplerImpl(bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>*, bvar::CombineCollected const&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>, bvar::detail::Sampler*, bvar::detail::CombineSampler>::SeriesSamplerImpl(bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>*, bvar::detail::CombineSampler const&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long> >::SeriesSamplerImpl(bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>*, bvar::detail::MaxTo<long> const&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long> >::SeriesSamplerImpl(bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >*, bvar::detail::AddTo<long> const&)
44
0
    void take_sample() override { _series.append(_owner->get_value()); }
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long> >::take_sample()
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>, bvar::Collected*, bvar::CombineCollected>::take_sample()
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>, bvar::detail::Sampler*, bvar::detail::CombineSampler>::take_sample()
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long> >::take_sample()
45
0
    void describe(std::ostream& os) { _series.describe(os, NULL); }
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>, long, bvar::detail::MaxTo<long> >::describe(std::basic_ostream<char, std::char_traits<char> >&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>, bvar::Collected*, bvar::CombineCollected>::describe(std::basic_ostream<char, std::char_traits<char> >&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>, bvar::detail::Sampler*, bvar::detail::CombineSampler>::describe(std::basic_ostream<char, std::char_traits<char> >&)
Unexecuted instantiation: bvar::detail::SeriesSamplerImpl<bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >, long, bvar::detail::AddTo<long> >::describe(std::basic_ostream<char, std::char_traits<char> >&)
46
47
private:
48
    O* _owner;
49
    Series<T, Op> _series;
50
};
51
52
#if WITH_BABYLON_COUNTER
53
template<typename T, typename Counter, typename Op, typename InvOp>
54
class BabylonVariable: public Variable {
55
public:
56
    typedef ReducerSampler<BabylonVariable, T, Op, InvOp> sampler_type;
57
    typedef SeriesSamplerImpl<BabylonVariable, T, Op> series_sampler_type;
58
59
    BabylonVariable() = default;
60
61
    template<typename U = T, typename std::enable_if<
62
        !std::is_constructible<Counter, U>::value, bool>::type = false>
63
    BabylonVariable(U) {}
64
    // For Maxer.
65
    template<typename U = T, typename std::enable_if<
66
        std::is_constructible<Counter, U>::value, bool>::type = false>
67
    BabylonVariable(U default_value) : _counter(default_value) {}
68
69
    DISALLOW_COPY_AND_MOVE(BabylonVariable);
70
71
    ~BabylonVariable() override {
72
        hide();
73
        if (NULL != _sampler) {
74
            _sampler->destroy();
75
        }
76
        if (NULL != _series_sampler) {
77
            _series_sampler->destroy();
78
        }
79
    }
80
81
    BabylonVariable& operator<<(T value) {
82
        _counter << value;
83
        return *this;
84
    }
85
86
    sampler_type* get_sampler() {
87
        if (NULL == _sampler) {
88
            _sampler = new sampler_type(this);
89
            _sampler->schedule();
90
        }
91
        return _sampler;
92
    }
93
94
    T get_value() const {
95
        return _counter.value();
96
    }
97
98
    T reset() {
99
        if (BAIDU_UNLIKELY((!butil::is_same<VoidOp, InvOp>::value))) {
100
            CHECK(false) << "You should not call Reducer<" << butil::class_name_str<T>()
101
                         << ", " << butil::class_name_str<Op>() << ">::get_value() when a"
102
                         << " Window<> is used because the operator does not have inverse.";
103
            return get_value();
104
        }
105
106
        T result = _counter.value();
107
        _counter.reset();
108
        return result;
109
    }
110
111
    bool valid() const { return true; }
112
113
    const Op& op() const { return _op; }
114
    const InvOp& inv_op() const { return _inv_op;}
115
116
    void describe(std::ostream& os, bool quote_string) const override {
117
        if (butil::is_same<T, std::string>::value && quote_string) {
118
            os << '"' << get_value() << '"';
119
        } else {
120
            os << get_value();
121
        }
122
    }
123
124
    int describe_series(std::ostream& os, const SeriesOptions& options) const override {
125
        if (NULL == _series_sampler) {
126
            return 1;
127
        }
128
        if (!options.test_only) {
129
            _series_sampler->describe(os);
130
        }
131
        return 0;
132
    }
133
134
protected:
135
    int expose_impl(const butil::StringPiece& prefix,
136
                    const butil::StringPiece& name,
137
                    DisplayFilter display_filter) override {
138
        const int rc = Variable::expose_impl(prefix, name, display_filter);
139
        if (rc == 0 && NULL == _series_sampler &&
140
            !butil::is_same<InvOp, VoidOp>::value &&
141
            !butil::is_same<T, std::string>::value &&
142
            FLAGS_save_series) {
143
            _series_sampler = new series_sampler_type(this, _op);
144
            _series_sampler->schedule();
145
        }
146
        return rc;
147
    }
148
149
private:
150
    Counter _counter;
151
    sampler_type* _sampler{NULL};
152
    series_sampler_type* _series_sampler{NULL};
153
    Op _op;
154
    InvOp _inv_op;
155
};
156
#endif // WITH_BABYLON_COUNTER
157
} // namespace detail
158
159
// Reduce multiple values into one with `Op': e1 Op e2 Op e3 ...
160
// `Op' shall satisfy:
161
//   - associative:     a Op (b Op c) == (a Op b) Op c
162
//   - commutative:     a Op b == b Op a;
163
//   - no side effects: a Op b never changes if a and b are fixed. 
164
// otherwise the result is undefined.
165
//
166
// For performance issues, we don't let Op return value, instead it shall
167
// set the result to the first parameter in-place. Namely to add two values,
168
// "+=" should be implemented rather than "+".
169
//
170
// Reducer works for non-primitive T which satisfies:
171
//   - T() should be the identity of Op.
172
//   - stream << v should compile and put description of v into the stream
173
// Example:
174
// class MyType {
175
// friend std::ostream& operator<<(std::ostream& os, const MyType&);
176
// public:
177
//     MyType() : _x(0) {}
178
//     explicit MyType(int x) : _x(x) {}
179
//     void operator+=(const MyType& rhs) const {
180
//         _x += rhs._x;
181
//     }
182
// private:
183
//     int _x;
184
// };
185
// std::ostream& operator<<(std::ostream& os, const MyType& value) {
186
//     return os << "MyType{" << value._x << "}";
187
// }
188
// bvar::Adder<MyType> my_type_sum;
189
// my_type_sum << MyType(1) << MyType(2) << MyType(3);
190
// LOG(INFO) << my_type_sum;  // "MyType{6}"
191
192
template <typename T, typename Op, typename InvOp = detail::VoidOp>
193
class Reducer : public Variable {
194
public:
195
    typedef detail::AgentCombiner<T, T, Op> combiner_type;
196
    typedef typename combiner_type::self_shared_type shared_combiner_type;
197
    typedef typename combiner_type::Agent agent_type;
198
    typedef detail::ReducerSampler<Reducer, T, Op, InvOp> sampler_type;
199
    typedef detail::SeriesSamplerImpl<Reducer, T, Op> SeriesSampler;
200
201
    // The `identify' must satisfy: identity Op a == a
202
    explicit Reducer(typename butil::add_cr_non_integral<T>::type identity = T(),
203
                     const Op& op = Op(), const InvOp& inv_op = InvOp())
204
2
        : _combiner(std::make_shared<combiner_type>(identity, identity, op))
205
2
        , _sampler(NULL) , _series_sampler(NULL) , _inv_op(inv_op) {}
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::Reducer(bvar::Collected* const&, bvar::CombineCollected const&, bvar::detail::VoidOp const&)
bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::Reducer(bvar::detail::Sampler* const&, bvar::detail::CombineSampler const&, bvar::detail::VoidOp const&)
Line
Count
Source
204
2
        : _combiner(std::make_shared<combiner_type>(identity, identity, op))
205
2
        , _sampler(NULL) , _series_sampler(NULL) , _inv_op(inv_op) {}
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::Reducer(long, bvar::detail::MaxTo<long> const&, bvar::detail::VoidOp const&)
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::Reducer(long, bvar::detail::AddTo<long> const&, bvar::detail::MinusFrom<long> const&)
206
207
0
    ~Reducer() override {
208
        // Calling hide() manually is a MUST required by Variable.
209
0
        hide();
210
0
        if (_sampler) {
211
0
            _sampler->destroy();
212
0
            _sampler = NULL;
213
0
        }
214
0
        if (_series_sampler) {
215
0
            _series_sampler->destroy();
216
0
            _series_sampler = NULL;
217
0
        }
218
0
    }
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::~Reducer()
Unexecuted instantiation: bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::~Reducer()
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::~Reducer()
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::~Reducer()
219
220
    // Add a value.
221
    // Returns self reference for chaining.
222
    Reducer& operator<<(typename butil::add_cr_non_integral<T>::type value);
223
224
    // Get reduced value.
225
    // Notice that this function walks through threads that ever add values
226
    // into this reducer. You should avoid calling it frequently.
227
0
    T get_value() const {
228
0
        CHECK(!(butil::is_same<InvOp, detail::VoidOp>::value) || _sampler == NULL)
229
0
            << "You should not call Reducer<" << butil::class_name_str<T>()
230
0
            << ", " << butil::class_name_str<Op>() << ">::get_value() when a"
231
0
            << " Window<> is used because the operator does not have inverse.";
232
0
        return _combiner->combine_agents();
233
0
    }
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::get_value() const
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::get_value() const
Unexecuted instantiation: bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::get_value() const
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::get_value() const
234
235
236
    // Reset the reduced value to T().
237
    // Returns the reduced value before reset.
238
6
    T reset() { return _combiner->reset_all_agents(); }
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::reset()
bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::reset()
Line
Count
Source
238
6
    T reset() { return _combiner->reset_all_agents(); }
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::reset()
239
240
0
    void describe(std::ostream& os, bool quote_string) const override {
241
0
        if (butil::is_same<T, std::string>::value && quote_string) {
242
0
            os << '"' << get_value() << '"';
243
0
        } else {
244
0
            os << get_value();
245
0
        }
246
0
    }
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::describe(std::basic_ostream<char, std::char_traits<char> >&, bool) const
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::describe(std::basic_ostream<char, std::char_traits<char> >&, bool) const
Unexecuted instantiation: bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::describe(std::basic_ostream<char, std::char_traits<char> >&, bool) const
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::describe(std::basic_ostream<char, std::char_traits<char> >&, bool) const
247
    
248
#ifdef BAIDU_INTERNAL
249
    void get_value(boost::any* value) const override { *value = get_value(); }
250
#endif
251
252
    // True if this reducer is constructed successfully.
253
    bool valid() const { return _combiner->valid(); }
254
255
    // Get instance of Op.
256
0
    const Op& op() const { return _combiner->op(); }
257
0
    const InvOp& inv_op() const { return _inv_op; }
258
    
259
0
    sampler_type* get_sampler() {
260
0
        if (NULL == _sampler) {
261
0
            _sampler = new sampler_type(this);
262
0
            _sampler->schedule();
263
0
        }
264
0
        return _sampler;
265
0
    }
266
267
0
    int describe_series(std::ostream& os, const SeriesOptions& options) const override {
268
0
        if (_series_sampler == NULL) {
269
0
            return 1;
270
0
        }
271
0
        if (!options.test_only) {
272
0
            _series_sampler->describe(os);
273
0
        }
274
0
        return 0;
275
0
    }
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::describe_series(std::basic_ostream<char, std::char_traits<char> >&, bvar::SeriesOptions const&) const
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::describe_series(std::basic_ostream<char, std::char_traits<char> >&, bvar::SeriesOptions const&) const
Unexecuted instantiation: bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::describe_series(std::basic_ostream<char, std::char_traits<char> >&, bvar::SeriesOptions const&) const
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::describe_series(std::basic_ostream<char, std::char_traits<char> >&, bvar::SeriesOptions const&) const
276
    
277
protected:
278
    int expose_impl(const butil::StringPiece& prefix,
279
                    const butil::StringPiece& name,
280
0
                    DisplayFilter display_filter) override {
281
0
        const int rc = Variable::expose_impl(prefix, name, display_filter);
282
0
        if (rc == 0 &&
283
0
            _series_sampler == NULL &&
284
0
            !butil::is_same<InvOp, detail::VoidOp>::value &&
285
0
            !butil::is_same<T, std::string>::value &&
286
0
            FLAGS_save_series) {
287
0
            _series_sampler = new SeriesSampler(this, _combiner->op());
288
0
            _series_sampler->schedule();
289
0
        }
290
0
        return rc;
291
0
    }
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::expose_impl(butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, bvar::DisplayFilter)
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::expose_impl(butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, bvar::DisplayFilter)
Unexecuted instantiation: bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::expose_impl(butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, bvar::DisplayFilter)
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::expose_impl(butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, butil::BasicStringPiece<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, bvar::DisplayFilter)
292
293
private:
294
    shared_combiner_type _combiner;
295
    sampler_type* _sampler;
296
    SeriesSampler* _series_sampler;
297
    InvOp _inv_op;
298
};
299
300
template <typename T, typename Op, typename InvOp>
301
inline Reducer<T, Op, InvOp>& Reducer<T, Op, InvOp>::operator<<(
302
8
    typename butil::add_cr_non_integral<T>::type value) {
303
    // It's wait-free for most time
304
8
    agent_type* agent = _combiner->get_or_create_tls_agent();
305
8
    if (__builtin_expect(!agent, 0)) {
306
0
        LOG(FATAL) << "Fail to create agent";
307
0
        return *this;
308
0
    }
309
8
    agent->element.modify(_combiner->op(), value);
310
8
    return *this;
311
8
}
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::AddTo<long>, bvar::detail::MinusFrom<long> >::operator<<(long)
Unexecuted instantiation: bvar::Reducer<bvar::Collected*, bvar::CombineCollected, bvar::detail::VoidOp>::operator<<(bvar::Collected* const&)
bvar::Reducer<bvar::detail::Sampler*, bvar::detail::CombineSampler, bvar::detail::VoidOp>::operator<<(bvar::detail::Sampler* const&)
Line
Count
Source
302
8
    typename butil::add_cr_non_integral<T>::type value) {
303
    // It's wait-free for most time
304
8
    agent_type* agent = _combiner->get_or_create_tls_agent();
305
8
    if (__builtin_expect(!agent, 0)) {
306
0
        LOG(FATAL) << "Fail to create agent";
307
0
        return *this;
308
0
    }
309
8
    agent->element.modify(_combiner->op(), value);
310
8
    return *this;
311
8
}
Unexecuted instantiation: bvar::Reducer<long, bvar::detail::MaxTo<long>, bvar::detail::VoidOp>::operator<<(long)
312
313
// =================== Common reducers ===================
314
315
// bvar::Adder<int> sum;
316
// sum << 1 << 2 << 3 << 4;
317
// LOG(INFO) << sum.get_value(); // 10
318
// Commonly used functors
319
namespace detail {
320
template <typename Tp>
321
struct AddTo {
322
    void operator()(Tp & lhs,
323
                    typename butil::add_cr_non_integral<Tp>::type rhs) const
324
0
    { lhs += rhs; }
Unexecuted instantiation: bvar::detail::AddTo<double>::operator()(double&, double const&) const
Unexecuted instantiation: bvar::detail::AddTo<long>::operator()(long&, long) const
Unexecuted instantiation: bvar::detail::AddTo<bvar::Vector<long, 4ul> >::operator()(bvar::Vector<long, 4ul>&, bvar::Vector<long, 4ul> const&) const
Unexecuted instantiation: bvar::detail::AddTo<unsigned long>::operator()(unsigned long&, unsigned long) const
Unexecuted instantiation: bvar::detail::AddTo<int>::operator()(int&, int) const
325
};
326
template <typename Tp>
327
struct MinusFrom {
328
    void operator()(Tp & lhs,
329
                    typename butil::add_cr_non_integral<Tp>::type rhs) const
330
0
    { lhs -= rhs; }
Unexecuted instantiation: bvar::detail::MinusFrom<double>::operator()(double&, double const&) const
Unexecuted instantiation: bvar::detail::MinusFrom<unsigned long>::operator()(unsigned long&, unsigned long) const
Unexecuted instantiation: bvar::detail::MinusFrom<long>::operator()(long&, long) const
331
};
332
} // namespace detail
333
334
template <typename T, typename = void>
335
class Adder : public Reducer<T, detail::AddTo<T>, detail::MinusFrom<T> > {
336
public:
337
    typedef Reducer<T, detail::AddTo<T>, detail::MinusFrom<T> > Base;
338
    typedef T value_type;
339
    typedef typename Base::sampler_type sampler_type;
340
341
    Adder() : Base() {}
342
0
    Adder(const butil::StringPiece& name) : Base() {
343
0
        this->expose(name);
344
0
    }
345
    Adder(const butil::StringPiece& prefix,
346
0
          const butil::StringPiece& name) : Base() {
347
0
        this->expose_as(prefix, name);
348
0
    }
349
0
    ~Adder() override { Variable::hide(); }
350
};
351
352
#if WITH_BABYLON_COUNTER
353
// Numerical types supported by babylon counter.
354
template <typename T>
355
class Adder<T, std::enable_if<std::is_constructible<babylon::GenericsConcurrentAdder<T>>::value>>
356
    : public detail::BabylonVariable<T, babylon::GenericsConcurrentAdder<T>,
357
                                     detail::AddTo<T>, detail::MinusFrom<T>> {
358
public:
359
    typedef  T value_type;
360
private:
361
    typedef detail::BabylonVariable<T, babylon::GenericsConcurrentAdder<T>,
362
                                    detail::AddTo<value_type>, detail::MinusFrom<value_type>> Base;
363
public:
364
    typedef detail::AddTo<value_type> Op;
365
    typedef detail::MinusFrom<value_type> InvOp;
366
    typedef typename Base::sampler_type sampler_type;
367
368
    COMMON_VARIABLE_CONSTRUCTOR(Adder);
369
};
370
#endif // WITH_BABYLON_COUNTER
371
372
// bvar::Maxer<int> max_value;
373
// max_value << 1 << 2 << 3 << 4;
374
// LOG(INFO) << max_value.get_value(); // 4
375
namespace detail {
376
template <typename Tp> 
377
struct MaxTo {
378
    void operator()(Tp & lhs, 
379
0
                    typename butil::add_cr_non_integral<Tp>::type rhs) const {
380
        // Use operator< as well.
381
0
        if (lhs < rhs) {
382
0
            lhs = rhs;
383
0
        }
384
0
    }
385
};
386
387
class LatencyRecorderBase;
388
} // namespace detail
389
390
template <typename T, typename = void>
391
class Maxer : public Reducer<T, detail::MaxTo<T> > {
392
public:
393
    typedef Reducer<T, detail::MaxTo<T> > Base;
394
    typedef T value_type;
395
    typedef typename Base::sampler_type sampler_type;
396
397
    Maxer() : Base(std::numeric_limits<T>::min()) {}
398
    Maxer(const butil::StringPiece& name)
399
        : Base(std::numeric_limits<T>::min()) {
400
        this->expose(name);
401
    }
402
    Maxer(const butil::StringPiece& prefix, const butil::StringPiece& name)
403
        : Base(std::numeric_limits<T>::min()) {
404
        this->expose_as(prefix, name);
405
    }
406
0
    ~Maxer() override { Variable::hide(); }
407
408
private:
409
    friend class detail::LatencyRecorderBase;
410
    // The following private funcition a now used in LatencyRecorder,
411
    // it's dangerous so we don't make them public
412
0
    explicit Maxer(T default_value) : Base(default_value) {
413
0
    }
414
    Maxer(T default_value, const butil::StringPiece& prefix,
415
          const butil::StringPiece& name) 
416
        : Base(default_value) {
417
        this->expose_as(prefix, name);
418
    }
419
    Maxer(T default_value, const butil::StringPiece& name) : Base(default_value) {
420
        this->expose(name);
421
    }
422
};
423
424
#if WITH_BABYLON_COUNTER
425
namespace detail {
426
template <typename T>
427
class ConcurrentMaxer : public babylon::GenericsConcurrentMaxer<T> {
428
    typedef babylon::GenericsConcurrentMaxer<T> Base;
429
public:
430
    ConcurrentMaxer() = default;
431
    ConcurrentMaxer(T default_value) : _default_value(default_value) {}
432
433
    T value() const {
434
        T result;
435
        if (!Base::value(result)) {
436
            return _default_value;
437
        }
438
        return std::max(result, _default_value);
439
    }
440
private:
441
    T _default_value{0};
442
};
443
} // namespace detail
444
445
// Numerical types supported by babylon counter.
446
template <typename T>
447
class Maxer<T, std::enable_if<std::is_constructible<detail::ConcurrentMaxer<T>>::value>>
448
    : public detail::BabylonVariable<T, detail::ConcurrentMaxer<T>,
449
                                     detail::MaxTo<T>, detail::VoidOp> {
450
public:
451
    typedef T value_type;
452
private:
453
    typedef detail::BabylonVariable<T, detail::ConcurrentMaxer<T>,
454
                                    detail::MaxTo<value_type>, detail::VoidOp> Base;
455
public:
456
    typedef detail::MaxTo<value_type> Op;
457
    typedef detail::VoidOp InvOp;
458
    typedef typename Base::sampler_type sampler_type;
459
460
    COMMON_VARIABLE_CONSTRUCTOR(Maxer);
461
462
private:
463
friend class detail::LatencyRecorderBase;
464
465
    Maxer(T default_value) : Base(default_value) {}
466
    Maxer(T default_value, const butil::StringPiece& prefix, const butil::StringPiece& name)
467
        : Base(default_value) {
468
        Variable::expose_as(prefix, name);
469
    }
470
    Maxer(T default_value, const butil::StringPiece& name)
471
        : Base(default_value) {
472
        Variable::expose(name);
473
    }
474
};
475
#endif // WITH_BABYLON_COUNTER
476
477
// bvar::Miner<int> min_value;
478
// min_value << 1 << 2 << 3 << 4;
479
// LOG(INFO) << min_value.get_value(); // 1
480
namespace detail {
481
template <typename Tp>
482
struct MinTo {
483
    void operator()(Tp & lhs,
484
                    typename butil::add_cr_non_integral<Tp>::type rhs) const {
485
        if (rhs < lhs) {
486
            lhs = rhs;
487
        }
488
    }
489
};
490
}  // namespace detail
491
492
template <typename T, typename = void>
493
class Miner : public Reducer<T, detail::MinTo<T> > {
494
public:
495
    typedef Reducer<T, detail::MinTo<T> > Base;
496
    typedef T value_type;
497
    typedef typename Base::sampler_type sampler_type;
498
499
    Miner() : Base(std::numeric_limits<T>::max()) {}
500
    Miner(const butil::StringPiece& name)
501
        : Base(std::numeric_limits<T>::max()) {
502
        this->expose(name);
503
    }
504
    Miner(const butil::StringPiece& prefix, const butil::StringPiece& name)
505
        : Base(std::numeric_limits<T>::max()) {
506
        this->expose_as(prefix, name);
507
    }
508
    ~Miner() override { Variable::hide(); }
509
};
510
511
#if WITH_BABYLON_COUNTER
512
// Numerical types supported by babylon counter.
513
template <typename T>
514
class Miner<T, std::enable_if<std::is_constructible<babylon::GenericsConcurrentMiner<T>>::value>>
515
    : public detail::BabylonVariable<T, babylon::GenericsConcurrentMiner<T>,
516
                                     detail::MinTo<T>, detail::VoidOp> {
517
public:
518
    typedef T value_type;
519
private:
520
    typedef detail::BabylonVariable<value_type, babylon::GenericsConcurrentMiner<T>,
521
                                    detail::MinTo<value_type>, detail::VoidOp> Base;
522
public:
523
    typedef detail::MinTo<value_type> Op;
524
    typedef detail::VoidOp InvOp;
525
    typedef typename Base::sampler_type sampler_type;
526
527
    COMMON_VARIABLE_CONSTRUCTOR(Miner);
528
};
529
#endif // WITH_BABYLON_COUNTER
530
531
}  // namespace bvar
532
533
#endif  //BVAR_REDUCER_H