Coverage Report

Created: 2026-04-09 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brpc/src/bvar/detail/combiner.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/22 11:57:43
19
20
#ifndef  BVAR_COMBINER_H
21
#define  BVAR_COMBINER_H
22
23
#include <string>                       // std::string
24
#include <vector>                       // std::vector
25
#include <memory>
26
#include "butil/atomicops.h"             // butil::atomic
27
#include "butil/scoped_lock.h"           // BAIDU_SCOPED_LOCK
28
#include "butil/type_traits.h"           // butil::add_cr_non_integral
29
#include "butil/synchronization/lock.h"  // butil::Lock
30
#include "butil/containers/linked_list.h"// LinkNode
31
#include "bvar/detail/agent_group.h"    // detail::AgentGroup
32
#include "bvar/detail/is_atomical.h"
33
#include "bvar/detail/call_op_returning_void.h"
34
35
namespace bvar {
36
namespace detail {
37
38
// Parameter to merge_global.
39
template <typename Combiner>
40
class GlobalValue {
41
public:
42
    typedef typename Combiner::result_type result_type;
43
    typedef typename Combiner::Agent agent_type;
44
45
0
    GlobalValue(agent_type* a, Combiner* c) : _a(a), _c(c) {}
46
47
    // Call this method to unlock tls element and lock the combiner.
48
    // Unlocking tls element avoids potential deadlock with
49
    // AgentCombiner::reset(), which also means that tls element may be
50
    // changed during calling of this method. BE AWARE OF THIS!
51
    // After this method is called (and before unlock), tls element and
52
    // global_result will not be changed provided this method is called
53
    // from the thread owning the agent.
54
0
    result_type* lock() {
55
0
        _a->element._lock.Release();
56
0
        _c->_lock.Acquire();
57
0
        return &_c->_global_result;
58
0
    }
59
60
    // Call this method to unlock the combiner and lock tls element again.
61
0
    void unlock() {
62
0
        _c->_lock.Release();
63
0
        _a->element._lock.Acquire();
64
0
    }
65
66
private:
67
    agent_type* _a;
68
    Combiner* _c;
69
};
70
71
// Abstraction of tls element whose operations are all atomic.
72
template <typename T, typename Enabler = void>
73
class ElementContainer {
74
template <typename> friend class GlobalValue;
75
public:
76
0
    void load(T* out) {
77
0
        butil::AutoLock guard(_lock);
78
0
        *out = _value;
79
0
    }
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::Collected*, void>::load(bvar::Collected**)
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::detail::Sampler*, void>::load(bvar::detail::Sampler**)
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::detail::PercentileSamples<30ul>, void>::load(bvar::detail::PercentileSamples<30ul>*)
80
81
30
    void store(const T& new_value) {
82
30
        butil::AutoLock guard(_lock);
83
30
        _value = new_value;
84
30
    }
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::Collected*, void>::store(bvar::Collected* const&)
bvar::detail::ElementContainer<bvar::detail::Sampler*, void>::store(bvar::detail::Sampler* const&)
Line
Count
Source
81
30
    void store(const T& new_value) {
82
30
        butil::AutoLock guard(_lock);
83
30
        _value = new_value;
84
30
    }
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::detail::PercentileSamples<30ul>, void>::store(bvar::detail::PercentileSamples<30ul> const&)
85
86
72
    void exchange(T* prev, const T& new_value) {
87
72
        butil::AutoLock guard(_lock);
88
72
        *prev = _value;
89
72
        _value = new_value;
90
72
    }
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::Collected*, void>::exchange(bvar::Collected**, bvar::Collected* const&)
bvar::detail::ElementContainer<bvar::detail::Sampler*, void>::exchange(bvar::detail::Sampler**, bvar::detail::Sampler* const&)
Line
Count
Source
86
72
    void exchange(T* prev, const T& new_value) {
87
72
        butil::AutoLock guard(_lock);
88
72
        *prev = _value;
89
72
        _value = new_value;
90
72
    }
Unexecuted instantiation: bvar::detail::ElementContainer<bvar::detail::PercentileSamples<30ul>, void>::exchange(bvar::detail::PercentileSamples<30ul>*, bvar::detail::PercentileSamples<30ul> const&)
91
92
    template <typename Op, typename T1>
93
178
    void modify(const Op &op, const T1 &value2) {
94
178
        butil::AutoLock guard(_lock);
95
178
        call_op_returning_void(op, _value, value2);
96
178
    }
Unexecuted instantiation: void bvar::detail::ElementContainer<bvar::Collected*, void>::modify<bvar::CombineCollected, bvar::Collected*>(bvar::CombineCollected const&, bvar::Collected* const&)
void bvar::detail::ElementContainer<bvar::detail::Sampler*, void>::modify<bvar::detail::CombineSampler, bvar::detail::Sampler*>(bvar::detail::CombineSampler const&, bvar::detail::Sampler* const&)
Line
Count
Source
93
178
    void modify(const Op &op, const T1 &value2) {
94
178
        butil::AutoLock guard(_lock);
95
178
        call_op_returning_void(op, _value, value2);
96
178
    }
97
98
    // [Unique]
99
    template <typename Op, typename GlobalValue>
100
0
    void merge_global(const Op &op, GlobalValue & global_value) {
101
0
        _lock.Acquire();
102
0
        op(global_value, _value);
103
0
        _lock.Release();
104
0
    }
105
106
private:
107
    T _value;
108
    butil::Lock _lock;
109
};
110
111
template <typename T>
112
class ElementContainer<
113
    T, typename butil::enable_if<is_atomical<T>::value>::type> {
114
public:
115
    // We don't need any memory fencing here, every op is relaxed.
116
    
117
0
    inline void load(T* out) {
118
0
        *out = _value.load(butil::memory_order_relaxed);
119
0
    }
Unexecuted instantiation: bvar::detail::ElementContainer<unsigned long, void>::load(unsigned long*)
Unexecuted instantiation: bvar::detail::ElementContainer<long, void>::load(long*)
Unexecuted instantiation: bvar::detail::ElementContainer<int, void>::load(int*)
120
121
4
    inline void store(T new_value) {
122
4
        _value.store(new_value, butil::memory_order_relaxed);
123
4
    }
Unexecuted instantiation: bvar::detail::ElementContainer<unsigned long, void>::store(unsigned long)
bvar::detail::ElementContainer<long, void>::store(long)
Line
Count
Source
121
4
    inline void store(T new_value) {
122
4
        _value.store(new_value, butil::memory_order_relaxed);
123
4
    }
Unexecuted instantiation: bvar::detail::ElementContainer<int, void>::store(int)
124
125
0
    inline void exchange(T* prev, T new_value) {
126
0
        *prev = _value.exchange(new_value, butil::memory_order_relaxed);
127
0
    }
Unexecuted instantiation: bvar::detail::ElementContainer<unsigned long, void>::exchange(unsigned long*, unsigned long)
Unexecuted instantiation: bvar::detail::ElementContainer<long, void>::exchange(long*, long)
Unexecuted instantiation: bvar::detail::ElementContainer<int, void>::exchange(int*, int)
128
129
    // [Unique]
130
0
    inline bool compare_exchange_weak(T& expected, T new_value) {
131
0
        return _value.compare_exchange_weak(expected, new_value,
132
0
                                            butil::memory_order_relaxed);
133
0
    }
134
135
    template <typename Op, typename T1>
136
4
    void modify(const Op &op, const T1 &value2) {
137
4
        T old_value = _value.load(butil::memory_order_relaxed);
138
4
        T new_value = old_value;
139
4
        call_op_returning_void(op, new_value, value2);
140
        // There's a contention with the reset operation of combiner,
141
        // if the tls value has been modified during _op, the
142
        // compare_exchange_weak operation will fail and recalculation is
143
        // to be processed according to the new version of value
144
4
        while (!_value.compare_exchange_weak(
145
4
                   old_value, new_value, butil::memory_order_relaxed)) {
146
0
            new_value = old_value;
147
0
            call_op_returning_void(op, new_value, value2);
148
0
        }
149
4
    }
void bvar::detail::ElementContainer<long, void>::modify<bvar::detail::AddTo<long>, long>(bvar::detail::AddTo<long> const&, long const&)
Line
Count
Source
136
4
    void modify(const Op &op, const T1 &value2) {
137
4
        T old_value = _value.load(butil::memory_order_relaxed);
138
4
        T new_value = old_value;
139
4
        call_op_returning_void(op, new_value, value2);
140
        // There's a contention with the reset operation of combiner,
141
        // if the tls value has been modified during _op, the
142
        // compare_exchange_weak operation will fail and recalculation is
143
        // to be processed according to the new version of value
144
4
        while (!_value.compare_exchange_weak(
145
4
                   old_value, new_value, butil::memory_order_relaxed)) {
146
0
            new_value = old_value;
147
0
            call_op_returning_void(op, new_value, value2);
148
0
        }
149
4
    }
Unexecuted instantiation: void bvar::detail::ElementContainer<long, void>::modify<bvar::detail::MaxTo<long>, long>(bvar::detail::MaxTo<long> const&, long const&)
Unexecuted instantiation: void bvar::detail::ElementContainer<int, void>::modify<bvar::detail::AddTo<int>, int>(bvar::detail::AddTo<int> const&, int const&)
Unexecuted instantiation: void bvar::detail::ElementContainer<unsigned long, void>::modify<bvar::detail::AddTo<unsigned long>, unsigned long>(bvar::detail::AddTo<unsigned long> const&, unsigned long const&)
150
151
private:
152
    butil::atomic<T> _value;
153
};
154
155
template <typename ResultTp, typename ElementTp, typename BinaryOp>
156
class AgentCombiner
157
    : public std::enable_shared_from_this<AgentCombiner<ResultTp, ElementTp, BinaryOp>> {
158
159
public:
160
    typedef ResultTp result_type;
161
    typedef ElementTp element_type;
162
    typedef AgentCombiner<ResultTp, ElementTp, BinaryOp> self_type;
163
    typedef std::shared_ptr<self_type> self_shared_type;
164
    typedef std::weak_ptr<self_type> self_weak_type;
165
friend class GlobalValue<self_type>;
166
167
    struct Agent : public butil::LinkNode<Agent> {
168
0
        ~Agent() {
169
0
            self_shared_type c = combiner.lock();
170
0
            if (NULL != c) {
171
0
                c->commit_and_erase(this);
172
0
            }
173
0
        }
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::Agent::~Agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::Agent::~Agent()
174
        
175
34
        void reset(const ElementTp& val, const self_shared_type& c) {
176
34
            combiner = c;
177
34
            element.store(val);
178
34
        }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::Agent::reset(unsigned long const&, std::shared_ptr<bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat> > const&)
bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::Agent::reset(long const&, std::shared_ptr<bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> > > const&)
Line
Count
Source
175
4
        void reset(const ElementTp& val, const self_shared_type& c) {
176
4
            combiner = c;
177
4
            element.store(val);
178
4
        }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::Agent::reset(bvar::Collected* const&, std::shared_ptr<bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected> > const&)
bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::Agent::reset(bvar::detail::Sampler* const&, std::shared_ptr<bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler> > const&)
Line
Count
Source
175
30
        void reset(const ElementTp& val, const self_shared_type& c) {
176
30
            combiner = c;
177
30
            element.store(val);
178
30
        }
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::Agent::reset(long const&, std::shared_ptr<bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> > > const&)
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::Agent::reset(bvar::detail::PercentileSamples<30ul> const&, std::shared_ptr<bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples> > const&)
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::Agent::reset(int const&, std::shared_ptr<bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> > > const&)
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::Agent::reset(unsigned long const&, std::shared_ptr<bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> > > const&)
179
180
        // Call op(GlobalValue<Combiner> &, ElementTp &) to merge tls element
181
        // into global_result. The common impl. is:
182
        //   struct XXX {
183
        //       void operator()(GlobalValue<Combiner> & global_value,
184
        //                       ElementTp & local_value) const {
185
        //           if (test_for_merging(local_value)) {
186
        // 
187
        //               // Unlock tls element and lock combiner. Obviously
188
        //               // tls element can be changed during lock().
189
        //               ResultTp* g = global_value.lock();
190
        // 
191
        //               // *g and local_value are not changed provided
192
        //               // merge_global is called from the thread owning
193
        //               // the agent.
194
        //               merge(*g, local_value);
195
        //
196
        //               // unlock combiner and lock tls element again.
197
        //               global_value.unlock();
198
        //           }
199
        //
200
        //           // safe to modify local_value because it's already locked
201
        //           // or locked again after merging.
202
        //           ...
203
        //       }
204
        //   };
205
        // 
206
        // NOTE: Only available to non-atomic types.
207
        template <typename Op>
208
0
        void merge_global(const Op &op, self_shared_type& c) {
209
0
            const self_shared_type& c_ref = NULL != c ? c : combiner.lock();
210
0
            if (NULL != c_ref) {
211
0
                GlobalValue<self_type> g(this, c_ref.get());
212
0
                element.merge_global(op, g);
213
0
            }
214
0
        }
215
216
        ElementContainer<ElementTp> element;
217
    private:
218
    friend class AgentCombiner<ResultTp, ElementTp, BinaryOp>;
219
        self_weak_type combiner;
220
    };
221
222
    typedef detail::AgentGroup<Agent> AgentGroup;
223
224
    explicit AgentCombiner(const ResultTp result_identity = ResultTp(),
225
                           const ElementTp element_identity = ElementTp(),
226
                           const BinaryOp& op = BinaryOp())
227
54
        : _id(AgentGroup::create_new_agent())
228
54
        , _op(op)
229
54
        , _global_result(result_identity)
230
54
        , _result_identity(result_identity)
231
54
        , _element_identity(element_identity) {
232
54
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::AgentCombiner(bvar::Collected*, bvar::Collected*, bvar::CombineCollected const&)
bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::AgentCombiner(bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler const&)
Line
Count
Source
227
30
        : _id(AgentGroup::create_new_agent())
228
30
        , _op(op)
229
30
        , _global_result(result_identity)
230
30
        , _result_identity(result_identity)
231
30
        , _element_identity(element_identity) {
232
30
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::AgentCombiner(bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat const&)
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::AgentCombiner(long, long, bvar::detail::MaxTo<long> const&)
bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::AgentCombiner(long, long, bvar::detail::AddTo<long> const&)
Line
Count
Source
227
20
        : _id(AgentGroup::create_new_agent())
228
20
        , _op(op)
229
20
        , _global_result(result_identity)
230
20
        , _result_identity(result_identity)
231
20
        , _element_identity(element_identity) {
232
20
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::AgentCombiner(bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples const&)
bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::AgentCombiner(int, int, bvar::detail::AddTo<int> const&)
Line
Count
Source
227
4
        : _id(AgentGroup::create_new_agent())
228
4
        , _op(op)
229
4
        , _global_result(result_identity)
230
4
        , _result_identity(result_identity)
231
4
        , _element_identity(element_identity) {
232
4
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::AgentCombiner(unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> const&)
233
234
0
    ~AgentCombiner() {
235
0
        if (_id >= 0) {
236
0
            clear_all_agents();
237
0
            AgentGroup::destroy_agent(_id);
238
0
            _id = -1;
239
0
        }
240
0
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::~AgentCombiner()
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::~AgentCombiner()
241
    
242
    // [Threadsafe] May be called from anywhere
243
12
    ResultTp combine_agents() const {
244
12
        ElementTp tls_value;
245
12
        butil::AutoLock guard(_lock);
246
12
        ResultTp ret = _global_result;
247
12
        for (butil::LinkNode<Agent>* node = _agents.head();
248
12
             node != _agents.end(); node = node->next()) {
249
0
            node->value()->element.load(&tls_value);
250
0
            call_op_returning_void(_op, ret, tls_value);
251
0
        }
252
12
        return ret;
253
12
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::combine_agents() const
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::combine_agents() const
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::combine_agents() const
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::combine_agents() const
bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::combine_agents() const
Line
Count
Source
243
8
    ResultTp combine_agents() const {
244
8
        ElementTp tls_value;
245
8
        butil::AutoLock guard(_lock);
246
8
        ResultTp ret = _global_result;
247
8
        for (butil::LinkNode<Agent>* node = _agents.head();
248
8
             node != _agents.end(); node = node->next()) {
249
0
            node->value()->element.load(&tls_value);
250
0
            call_op_returning_void(_op, ret, tls_value);
251
0
        }
252
8
        return ret;
253
8
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::combine_agents() const
bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::combine_agents() const
Line
Count
Source
243
4
    ResultTp combine_agents() const {
244
4
        ElementTp tls_value;
245
4
        butil::AutoLock guard(_lock);
246
4
        ResultTp ret = _global_result;
247
4
        for (butil::LinkNode<Agent>* node = _agents.head();
248
4
             node != _agents.end(); node = node->next()) {
249
0
            node->value()->element.load(&tls_value);
250
0
            call_op_returning_void(_op, ret, tls_value);
251
0
        }
252
4
        return ret;
253
4
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::combine_agents() const
254
255
    typename butil::add_cr_non_integral<ElementTp>::type
256
    element_identity() const { return _element_identity; }
257
    typename butil::add_cr_non_integral<ResultTp>::type
258
    result_identity() const { return _result_identity; }
259
260
    // [Threadsafe] May be called from anywhere.
261
72
    ResultTp reset_all_agents() {
262
72
        ElementTp prev;
263
72
        butil::AutoLock guard(_lock);
264
72
        ResultTp tmp = _global_result;
265
72
        _global_result = _result_identity;
266
72
        for (butil::LinkNode<Agent>* node = _agents.head();
267
144
             node != _agents.end(); node = node->next()) {
268
72
            node->value()->element.exchange(&prev, _element_identity);
269
72
            call_op_returning_void(_op, tmp, prev);
270
72
        }
271
72
        return tmp;
272
72
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::reset_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::reset_all_agents()
bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::reset_all_agents()
Line
Count
Source
261
72
    ResultTp reset_all_agents() {
262
72
        ElementTp prev;
263
72
        butil::AutoLock guard(_lock);
264
72
        ResultTp tmp = _global_result;
265
72
        _global_result = _result_identity;
266
72
        for (butil::LinkNode<Agent>* node = _agents.head();
267
144
             node != _agents.end(); node = node->next()) {
268
72
            node->value()->element.exchange(&prev, _element_identity);
269
72
            call_op_returning_void(_op, tmp, prev);
270
72
        }
271
72
        return tmp;
272
72
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::reset_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::reset_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::reset_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::reset_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::reset_all_agents()
273
274
    // Always called from the thread owning the agent.
275
0
    void commit_and_erase(Agent* agent) {
276
0
        if (NULL == agent) {
277
0
            return;
278
0
        }
279
0
        ElementTp local;
280
0
        butil::AutoLock guard(_lock);
281
        // TODO: For non-atomic types, we can pass the reference to op directly.
282
        // But atomic types cannot. The code is a little troublesome to write.
283
0
        agent->element.load(&local);
284
0
        call_op_returning_void(_op, _global_result, local);
285
0
        agent->RemoveFromList();
286
0
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::commit_and_erase(bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::commit_and_erase(bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::commit_and_erase(bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::commit_and_erase(bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::commit_and_erase(bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::commit_and_erase(bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::commit_and_erase(bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::Agent*)
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::commit_and_erase(bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::Agent*)
287
288
    // Always called from the thread owning the agent
289
0
    void commit_and_clear(Agent* agent) {
290
0
        if (NULL == agent) {
291
0
            return;
292
0
        }
293
0
        ElementTp prev;
294
0
        butil::AutoLock guard(_lock);
295
0
        agent->element.exchange(&prev, _element_identity);
296
0
        call_op_returning_void(_op, _global_result, prev);
297
0
    }
298
299
    // We need this function to be as fast as possible.
300
182
    Agent* get_or_create_tls_agent() {
301
182
        Agent* agent = AgentGroup::get_tls_agent(_id);
302
182
        if (!agent) {
303
            // Create the agent
304
34
            agent = AgentGroup::get_or_create_tls_agent(_id);
305
34
            if (NULL == agent) {
306
0
                LOG(FATAL) << "Fail to create agent";
307
0
                return NULL;
308
0
            }
309
34
        }
310
182
        if (!agent->combiner.expired()) {
311
148
            return agent;
312
148
        }
313
34
        agent->reset(_element_identity, this->shared_from_this());
314
        // TODO: Is uniqueness-checking necessary here?
315
34
        {
316
34
            butil::AutoLock guard(_lock);
317
34
            _agents.Append(agent);
318
34
        }
319
34
        return agent;
320
182
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::get_or_create_tls_agent()
bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::get_or_create_tls_agent()
Line
Count
Source
300
4
    Agent* get_or_create_tls_agent() {
301
4
        Agent* agent = AgentGroup::get_tls_agent(_id);
302
4
        if (!agent) {
303
            // Create the agent
304
4
            agent = AgentGroup::get_or_create_tls_agent(_id);
305
4
            if (NULL == agent) {
306
0
                LOG(FATAL) << "Fail to create agent";
307
0
                return NULL;
308
0
            }
309
4
        }
310
4
        if (!agent->combiner.expired()) {
311
0
            return agent;
312
0
        }
313
4
        agent->reset(_element_identity, this->shared_from_this());
314
        // TODO: Is uniqueness-checking necessary here?
315
4
        {
316
4
            butil::AutoLock guard(_lock);
317
4
            _agents.Append(agent);
318
4
        }
319
4
        return agent;
320
4
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::get_or_create_tls_agent()
bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::get_or_create_tls_agent()
Line
Count
Source
300
178
    Agent* get_or_create_tls_agent() {
301
178
        Agent* agent = AgentGroup::get_tls_agent(_id);
302
178
        if (!agent) {
303
            // Create the agent
304
30
            agent = AgentGroup::get_or_create_tls_agent(_id);
305
30
            if (NULL == agent) {
306
0
                LOG(FATAL) << "Fail to create agent";
307
0
                return NULL;
308
0
            }
309
30
        }
310
178
        if (!agent->combiner.expired()) {
311
148
            return agent;
312
148
        }
313
30
        agent->reset(_element_identity, this->shared_from_this());
314
        // TODO: Is uniqueness-checking necessary here?
315
30
        {
316
30
            butil::AutoLock guard(_lock);
317
30
            _agents.Append(agent);
318
30
        }
319
30
        return agent;
320
178
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::get_or_create_tls_agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::get_or_create_tls_agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::get_or_create_tls_agent()
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::get_or_create_tls_agent()
321
322
0
    void clear_all_agents() {
323
0
        butil::AutoLock guard(_lock);
324
        // Resting agents is must because the agent object may be reused.
325
        // Set element to be default-constructed so that if it's non-pod,
326
        // internal allocations should be released.
327
0
        for (butil::LinkNode<Agent>* node = _agents.head(); node != _agents.end();) {
328
0
            node->value()->reset(ElementTp(), NULL);
329
0
            butil::LinkNode<Agent>* const saved_next =  node->next();
330
0
            node->RemoveFromList();
331
0
            node = saved_next;
332
0
        }
333
0
    }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::clear_all_agents()
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::clear_all_agents()
334
335
198
    const BinaryOp& op() const { return _op; }
Unexecuted instantiation: bvar::detail::AgentCombiner<long, long, bvar::detail::MaxTo<long> >::op() const
bvar::detail::AgentCombiner<long, long, bvar::detail::AddTo<long> >::op() const
Line
Count
Source
335
20
    const BinaryOp& op() const { return _op; }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Collected*, bvar::Collected*, bvar::CombineCollected>::op() const
bvar::detail::AgentCombiner<bvar::detail::Sampler*, bvar::detail::Sampler*, bvar::detail::CombineSampler>::op() const
Line
Count
Source
335
178
    const BinaryOp& op() const { return _op; }
Unexecuted instantiation: bvar::detail::AgentCombiner<int, int, bvar::detail::AddTo<int> >::op() const
Unexecuted instantiation: bvar::detail::AgentCombiner<unsigned long, unsigned long, bvar::detail::AddTo<unsigned long> >::op() const
336
337
0
    bool valid() const { return _id >= 0; }
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::Stat, unsigned long, bvar::IntRecorder::AddToStat>::valid() const
Unexecuted instantiation: bvar::detail::AgentCombiner<bvar::detail::PercentileSamples<254ul>, bvar::detail::PercentileSamples<30ul>, bvar::detail::detail::AddPercentileSamples>::valid() const
338
339
private:
340
    AgentId                                     _id;
341
    BinaryOp                                    _op;
342
    mutable butil::Lock                          _lock;
343
    ResultTp                                    _global_result;
344
    ResultTp                                    _result_identity;
345
    ElementTp                                   _element_identity;
346
    butil::LinkedList<Agent>                     _agents;
347
};
348
349
}  // namespace detail
350
}  // namespace bvar
351
352
#endif  // BVAR_COMBINER_H