2020#ifndef BVAR_MULTI_DIMENSION_H
2121#define BVAR_MULTI_DIMENSION_H
2222
23+ #include < memory>
24+ #include < type_traits>
2325#include " butil/logging.h" // LOG
2426#include " butil/macros.h" // BAIDU_CASSERT
2527#include " butil/scoped_lock.h" // BAIDU_SCOPE_LOCK
@@ -35,8 +37,14 @@ namespace bvar {
3537// 2. KeyType::value_type must be std::string.
3638// 3. KeyType::size() returns the number of labels.
3739// 4. KeyType::push_back() adds a label to the end of the container.
38- template <typename T, typename KeyType = std::list<std::string>>
40+ //
41+ // If `Shared' is false, `get_stats' returns a raw pointer,
42+ // `delete_stats' and `clear_stats' are not thread safe.
43+ // If `Shared' is true, `get_stats` returns a shared_ptr,
44+ // `delete_stats' and `clear_stats' are thread safe.
45+ template <typename T, typename KeyType = std::list<std::string>, bool Shared = false >
3946class MultiDimension : public MVariable <KeyType> {
47+ typedef std::shared_ptr<T> shared_value_type;
4048public:
4149 enum STATS_OP {
4250 READ_ONLY,
@@ -45,7 +53,7 @@ class MultiDimension : public MVariable<KeyType> {
4553
4654 typedef KeyType key_type;
4755 typedef T value_type;
48- typedef T* value_ptr_type;
56+ typedef typename std::conditional<Shared, shared_value_type, T*>::type value_ptr_type;
4957 typedef MVariable<key_type> Base;
5058
5159 struct KeyHash {
@@ -102,11 +110,15 @@ class MultiDimension : public MVariable<KeyType> {
102110 // 2. K::value_type must be able to convert to std::string and butil::StringPiece
103111 // through operator std::string() function and operator butil::StringPiece() function.
104112 // 3. K::value_type must be able to compare with std::string.
113+ //
114+ // Returns a shared_ptr if `Shared' is true, otherwise returns a raw pointer.
105115 template <typename K = key_type>
106- T* get_stats (const K& labels_value) {
116+ value_ptr_type get_stats (const K& labels_value) {
107117 return get_stats_impl (labels_value, READ_OR_INSERT);
108118 }
109119
120+ // `delete_stats' and `clear_stats' are thread safe
121+ // if `Shared' is true, otherwise not.
110122 // Remove stat so those not count and dump
111123 template <typename K = key_type>
112124 void delete_stats (const K& labels_value);
@@ -133,25 +145,26 @@ class MultiDimension : public MVariable<KeyType> {
133145 // Return real bvar pointer if labels_name exist, NULL otherwise.
134146 // CAUTION!!! Just For Debug!!!
135147 template <typename K = key_type>
136- T* get_stats_read_only (const K& labels_value) {
148+ value_ptr_type get_stats_read_only (const K& labels_value) {
137149 return get_stats_impl (labels_value);
138150 }
139151
140152 // Get real bvar pointer object
141153 // Return real bvar pointer if labels_name exist, otherwise(not exist) create bvar pointer.
142154 // CAUTION!!! Just For Debug!!!
143155 template <typename K = key_type>
144- T* get_stats_read_or_insert (const K& labels_value, bool * do_write = NULL ) {
156+ value_ptr_type get_stats_read_or_insert (const K& labels_value, bool * do_write = NULL ) {
145157 return get_stats_impl (labels_value, READ_OR_INSERT, do_write);
146158 }
147159#endif
148160
149161private:
150162 template <typename K>
151- T* get_stats_impl (const K& labels_value);
163+ value_ptr_type get_stats_impl (const K& labels_value);
152164
153165 template <typename K>
154- T* get_stats_impl (const K& labels_value, STATS_OP stats_op, bool * do_write = NULL );
166+ value_ptr_type get_stats_impl (
167+ const K& labels_value, STATS_OP stats_op, bool * do_write = NULL );
155168
156169 template <typename K>
157170 static typename std::enable_if<butil::is_same<K, key_type>::value>::type
@@ -162,11 +175,8 @@ class MultiDimension : public MVariable<KeyType> {
162175 template <typename K>
163176 static typename std::enable_if<!butil::is_same<K, key_type>::value>::type
164177 insert_metrics_map (MetricMap& bg, const K& labels_value, op_value_type metric) {
165- key_type labels_value_str;
166- for (auto & label : labels_value) {
167- // key_type::value_type must be able to convert to std::string.
168- labels_value_str.push_back (std::string (label));
169- }
178+ // key_type::value_type must be able to convert to std::string.
179+ key_type labels_value_str (labels_value.cbegin (), labels_value.cend ());
170180 bg.insert (labels_value_str, metric);
171181 }
172182
@@ -192,7 +202,27 @@ class MultiDimension : public MVariable<KeyType> {
192202 void delete_stats ();
193203
194204 static size_t init_flatmap (MetricMap& bg);
195-
205+
206+ // If Shared is true, return std::shared_ptr, otherwise return raw pointer.
207+ template <bool S = Shared>
208+ typename std::enable_if<S, value_ptr_type>::type new_value () {
209+ return std::make_shared<value_type>();
210+ }
211+ template <bool S = Shared>
212+ typename std::enable_if<!S, value_ptr_type>::type new_value () {
213+ return new value_type ();
214+ }
215+
216+ // If Shared is true, reset std::shared_ptr, otherwise delete raw pointer.
217+ template <bool S = Shared>
218+ typename std::enable_if<S>::type delete_value (value_ptr_type& v) {
219+ v.reset ();
220+ }
221+ template <bool S = Shared>
222+ typename std::enable_if<!S>::type delete_value (value_ptr_type& v) {
223+ delete v;
224+ }
225+
196226 size_t _max_stats_count;
197227 MetricMapDBD _metric_map;
198228};
0 commit comments