• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()102 const 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)114 void 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