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 
Config()70   Config() {}
~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 {
~BaseOptionBaseOption82     virtual ~BaseOption() {}
83   };
84 
85   template<typename T>
86   struct Option : BaseOption {
OptionOption87     explicit Option(T* v): value(v) {}
~OptionOption88     ~Option() {
89       delete value;
90     }
91     T* value;
92   };
93 
94   template<typename T>
identifier()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>
default_value()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>
Get()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>
Set(T * value)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