blob: 6ead4098d33ec00e6341e4c0ea978b4236617a7c [file] [log] [blame]
andresp@webrtc.org1dba6212013-05-13 08:06:36 +00001/*
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
andrew@webrtc.org25613ea2013-07-25 18:28:29 +000011#ifndef WEBRTC_COMMON_H_
12#define WEBRTC_COMMON_H_
andresp@webrtc.org1dba6212013-05-13 08:06:36 +000013
14#include <map>
15
16namespace 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).
38class Config {
39 public:
40 // Returns the option if set or a default constructed one.
andrew@webrtc.org25613ea2013-07-25 18:28:29 +000041 // Callers that access options too often are encouraged to cache the result.
andresp@webrtc.org1dba6212013-05-13 08:06:36 +000042 // 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.
andrew@webrtc.org25613ea2013-07-25 18:28:29 +000048 // This instance gets ownership of the newly set value.
andresp@webrtc.org1dba6212013-05-13 08:06:36 +000049 template<typename T> void Set(T* value);
50
51 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 {
65 virtual ~BaseOption() {}
66 };
67
68 template<typename T>
69 struct Option : BaseOption {
70 explicit Option(T* v): value(v) {}
71 ~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>
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>
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
101template<typename T>
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
113template<typename T>
114void Config::Set(T* value) {
115 BaseOption*& it = options_[identifier<T>()];
116 delete it;
117 it = new Option<T>(value);
118}
andrew@webrtc.org25613ea2013-07-25 18:28:29 +0000119
andresp@webrtc.org1dba6212013-05-13 08:06:36 +0000120} // namespace webrtc
andrew@webrtc.org25613ea2013-07-25 18:28:29 +0000121
122#endif // WEBRTC_COMMON_H_