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,15 @@ 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+ // Note: The shared mode may be less performant than the non-shared mode.
46+ template <typename T, typename KeyType = std::list<std::string>, bool Shared = false >
3947class MultiDimension : public MVariable <KeyType> {
48+ typedef std::shared_ptr<T> shared_value_type;
4049public:
4150 enum STATS_OP {
4251 READ_ONLY,
@@ -45,7 +54,7 @@ class MultiDimension : public MVariable<KeyType> {
4554
4655 typedef KeyType key_type;
4756 typedef T value_type;
48- typedef T* value_ptr_type;
57+ typedef typename std::conditional<Shared, shared_value_type, T*>::type value_ptr_type;
4958 typedef MVariable<key_type> Base;
5059
5160 struct KeyHash {
@@ -102,11 +111,15 @@ class MultiDimension : public MVariable<KeyType> {
102111 // 2. K::value_type must be able to convert to std::string and butil::StringPiece
103112 // through operator std::string() function and operator butil::StringPiece() function.
104113 // 3. K::value_type must be able to compare with std::string.
114+ //
115+ // Returns a shared_ptr if `Shared' is true, otherwise returns a raw pointer.
105116 template <typename K = key_type>
106- T* get_stats (const K& labels_value) {
117+ value_ptr_type get_stats (const K& labels_value) {
107118 return get_stats_impl (labels_value, READ_OR_INSERT);
108119 }
109120
121+ // `delete_stats' and `clear_stats' are thread safe
122+ // if `Shared' is true, otherwise not.
110123 // Remove stat so those not count and dump
111124 template <typename K = key_type>
112125 void delete_stats (const K& labels_value);
@@ -133,25 +146,26 @@ class MultiDimension : public MVariable<KeyType> {
133146 // Return real bvar pointer if labels_name exist, NULL otherwise.
134147 // CAUTION!!! Just For Debug!!!
135148 template <typename K = key_type>
136- T* get_stats_read_only (const K& labels_value) {
149+ value_ptr_type get_stats_read_only (const K& labels_value) {
137150 return get_stats_impl (labels_value);
138151 }
139152
140153 // Get real bvar pointer object
141154 // Return real bvar pointer if labels_name exist, otherwise(not exist) create bvar pointer.
142155 // CAUTION!!! Just For Debug!!!
143156 template <typename K = key_type>
144- T* get_stats_read_or_insert (const K& labels_value, bool * do_write = NULL ) {
157+ value_ptr_type get_stats_read_or_insert (const K& labels_value, bool * do_write = NULL ) {
145158 return get_stats_impl (labels_value, READ_OR_INSERT, do_write);
146159 }
147160#endif
148161
149162private:
150163 template <typename K>
151- T* get_stats_impl (const K& labels_value);
164+ value_ptr_type get_stats_impl (const K& labels_value);
152165
153166 template <typename K>
154- T* get_stats_impl (const K& labels_value, STATS_OP stats_op, bool * do_write = NULL );
167+ value_ptr_type get_stats_impl (
168+ const K& labels_value, STATS_OP stats_op, bool * do_write = NULL );
155169
156170 template <typename K>
157171 static typename std::enable_if<butil::is_same<K, key_type>::value>::type
@@ -162,11 +176,8 @@ class MultiDimension : public MVariable<KeyType> {
162176 template <typename K>
163177 static typename std::enable_if<!butil::is_same<K, key_type>::value>::type
164178 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- }
179+ // key_type::value_type must be able to convert to std::string.
180+ key_type labels_value_str (labels_value.cbegin (), labels_value.cend ());
170181 bg.insert (labels_value_str, metric);
171182 }
172183
@@ -192,7 +203,27 @@ class MultiDimension : public MVariable<KeyType> {
192203 void delete_stats ();
193204
194205 static size_t init_flatmap (MetricMap& bg);
195-
206+
207+ // If Shared is true, return std::shared_ptr, otherwise return raw pointer.
208+ template <bool S = Shared>
209+ typename std::enable_if<S, value_ptr_type>::type new_value () {
210+ return std::make_shared<value_type>();
211+ }
212+ template <bool S = Shared>
213+ typename std::enable_if<!S, value_ptr_type>::type new_value () {
214+ return new value_type ();
215+ }
216+
217+ // If Shared is true, reset std::shared_ptr, otherwise delete raw pointer.
218+ template <bool S = Shared>
219+ typename std::enable_if<S>::type delete_value (value_ptr_type& v) {
220+ v.reset ();
221+ }
222+ template <bool S = Shared>
223+ typename std::enable_if<!S>::type delete_value (value_ptr_type& v) {
224+ delete v;
225+ }
226+
196227 size_t _max_stats_count;
197228 MetricMapDBD _metric_map;
198229};
0 commit comments