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