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 namespace webrtc { 17 18 // Class Config is designed to ease passing a set of options across webrtc code. 19 // Options are identified by typename in order to avoid incorrect casts. 20 // 21 // Usage: 22 // * declaring an option: 23 // struct Algo1_CostFunction { 24 // virtual float cost(int x) const { return x; } 25 // virtual ~Algo1_CostFunction() {} 26 // }; 27 // 28 // * accessing an option: 29 // config.Get<Algo1_CostFunction>().cost(value); 30 // 31 // * setting an option: 32 // struct SqrCost : Algo1_CostFunction { 33 // virtual float cost(int x) const { return x*x; } 34 // }; 35 // config.Set<Algo1_CostFunction>(new SqrCost()); 36 // 37 // Note: This class is thread-compatible (like STL containers). 38 class Config { 39 public: 40 // Returns the option if set or a default constructed one. 41 // Callers that access options too often are encouraged to cache the result. 42 // Returned references are owned by this. 43 // 44 // Requires std::is_default_constructible<T> 45 template<typename T> const T& Get() const; 46 47 // Set the option, deleting any previous instance of the same. 48 // This instance gets ownership of the newly set value. 49 template<typename T> void Set(T* value); 50 Config()51 Config() {} ~Config()52 ~Config() { 53 // Note: this method is inline so webrtc public API depends only 54 // on the headers. 55 for (OptionMap::iterator it = options_.begin(); 56 it != options_.end(); ++it) { 57 delete it->second; 58 } 59 } 60 61 private: 62 typedef void* OptionIdentifier; 63 64 struct BaseOption { ~BaseOptionBaseOption65 virtual ~BaseOption() {} 66 }; 67 68 template<typename T> 69 struct Option : BaseOption { OptionOption70 explicit Option(T* v): value(v) {} ~OptionOption71 ~Option() { 72 delete value; 73 } 74 T* value; 75 }; 76 77 // Own implementation of rtti-subset to avoid depending on rtti and its costs. 78 template<typename T> identifier()79 static OptionIdentifier identifier() { 80 static char id_placeholder; 81 return &id_placeholder; 82 } 83 84 // Used to instantiate a default constructed object that doesn't needs to be 85 // owned. This allows Get<T> to be implemented without requiring explicitly 86 // locks. 87 template<typename T> default_value()88 static const T& default_value() { 89 static const T def; 90 return def; 91 } 92 93 typedef std::map<OptionIdentifier, BaseOption*> OptionMap; 94 OptionMap options_; 95 96 // DISALLOW_COPY_AND_ASSIGN 97 Config(const Config&); 98 void operator=(const Config&); 99 }; 100 101 template<typename T> Get()102const T& Config::Get() const { 103 OptionMap::const_iterator it = options_.find(identifier<T>()); 104 if (it != options_.end()) { 105 const T* t = static_cast<Option<T>*>(it->second)->value; 106 if (t) { 107 return *t; 108 } 109 } 110 return default_value<T>(); 111 } 112 113 template<typename T> Set(T * value)114void Config::Set(T* value) { 115 BaseOption*& it = options_[identifier<T>()]; 116 delete it; 117 it = new Option<T>(value); 118 } 119 120 } // namespace webrtc 121 122 #endif // WEBRTC_COMMON_H_ 123