1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_COMMON_H_ 12 #define WEBRTC_COMMON_H_ 13 14 #include <map> 15 16 #include "webrtc/base/basictypes.h" 17 18 namespace webrtc { 19 20 // Only add new values to the end of the enumeration and never remove (only 21 // deprecate) to maintain binary compatibility. 22 enum class ConfigOptionID { 23 kMyExperimentForTest, 24 kAlgo1CostFunctionForTest, 25 kTemporalLayersFactory, 26 kNetEqCapacityConfig, 27 kNetEqFastAccelerate, 28 kVoicePacing, 29 kExtendedFilter, 30 kDelayAgnostic, 31 kExperimentalAgc, 32 kExperimentalNs, 33 kBeamforming, 34 kIntelligibility 35 }; 36 37 // Class Config is designed to ease passing a set of options across webrtc code. 38 // Options are identified by typename in order to avoid incorrect casts. 39 // 40 // Usage: 41 // * declaring an option: 42 // struct Algo1_CostFunction { 43 // virtual float cost(int x) const { return x; } 44 // virtual ~Algo1_CostFunction() {} 45 // }; 46 // 47 // * accessing an option: 48 // config.Get<Algo1_CostFunction>().cost(value); 49 // 50 // * setting an option: 51 // struct SqrCost : Algo1_CostFunction { 52 // virtual float cost(int x) const { return x*x; } 53 // }; 54 // config.Set<Algo1_CostFunction>(new SqrCost()); 55 // 56 // Note: This class is thread-compatible (like STL containers). 57 class Config { 58 public: 59 // Returns the option if set or a default constructed one. 60 // Callers that access options too often are encouraged to cache the result. 61 // Returned references are owned by this. 62 // 63 // Requires std::is_default_constructible<T> 64 template<typename T> const T& Get() const; 65 66 // Set the option, deleting any previous instance of the same. 67 // This instance gets ownership of the newly set value. 68 template<typename T> void Set(T* value); 69 70 Config() {} 71 ~Config() { 72 // Note: this method is inline so webrtc public API depends only 73 // on the headers. 74 for (OptionMap::iterator it = options_.begin(); 75 it != options_.end(); ++it) { 76 delete it->second; 77 } 78 } 79 80 private: 81 struct BaseOption { 82 virtual ~BaseOption() {} 83 }; 84 85 template<typename T> 86 struct Option : BaseOption { 87 explicit Option(T* v): value(v) {} 88 ~Option() { 89 delete value; 90 } 91 T* value; 92 }; 93 94 template<typename T> 95 static ConfigOptionID identifier() { 96 return T::identifier; 97 } 98 99 // Used to instantiate a default constructed object that doesn't needs to be 100 // owned. This allows Get<T> to be implemented without requiring explicitly 101 // locks. 102 template<typename T> 103 static const T& default_value() { 104 RTC_DEFINE_STATIC_LOCAL(const T, def, ()); 105 return def; 106 } 107 108 typedef std::map<ConfigOptionID, BaseOption*> OptionMap; 109 OptionMap options_; 110 111 // RTC_DISALLOW_COPY_AND_ASSIGN 112 Config(const Config&); 113 void operator=(const Config&); 114 }; 115 116 template<typename T> 117 const T& Config::Get() const { 118 OptionMap::const_iterator it = options_.find(identifier<T>()); 119 if (it != options_.end()) { 120 const T* t = static_cast<Option<T>*>(it->second)->value; 121 if (t) { 122 return *t; 123 } 124 } 125 return default_value<T>(); 126 } 127 128 template<typename T> 129 void Config::Set(T* value) { 130 BaseOption*& it = options_[identifier<T>()]; 131 delete it; 132 it = new Option<T>(value); 133 } 134 135 } // namespace webrtc 136 137 #endif // WEBRTC_COMMON_H_ 138