blob: d0d7eb192c341569c2929c14747d5b5bb31f276a [file] [log] [blame]
andresp@webrtc.org6b68c282013-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.org61e596f2013-07-25 18:28:29 +000011#ifndef WEBRTC_COMMON_H_
12#define WEBRTC_COMMON_H_
andresp@webrtc.org6b68c282013-05-13 08:06:36 +000013
14#include <map>
15
Andrew MacDonald469c2c02015-05-22 17:50:26 -070016#include "webrtc/base/basictypes.h"
17
andresp@webrtc.org6b68c282013-05-13 08:06:36 +000018namespace 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).
40class Config {
41 public:
42 // Returns the option if set or a default constructed one.
andrew@webrtc.org61e596f2013-07-25 18:28:29 +000043 // Callers that access options too often are encouraged to cache the result.
andresp@webrtc.org6b68c282013-05-13 08:06:36 +000044 // 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.
andrew@webrtc.org61e596f2013-07-25 18:28:29 +000050 // This instance gets ownership of the newly set value.
andresp@webrtc.org6b68c282013-05-13 08:06:36 +000051 template<typename T> void Set(T* value);
52
53 Config() {}
54 ~Config() {
55 // Note: this method is inline so webrtc public API depends only
56 // on the headers.
57 for (OptionMap::iterator it = options_.begin();
58 it != options_.end(); ++it) {
59 delete it->second;
60 }
61 }
62
63 private:
64 typedef void* OptionIdentifier;
65
66 struct BaseOption {
67 virtual ~BaseOption() {}
68 };
69
70 template<typename T>
71 struct Option : BaseOption {
72 explicit Option(T* v): value(v) {}
73 ~Option() {
74 delete value;
75 }
76 T* value;
77 };
78
79 // Own implementation of rtti-subset to avoid depending on rtti and its costs.
80 template<typename T>
81 static OptionIdentifier identifier() {
82 static char id_placeholder;
83 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() {
Andrew MacDonald469c2c02015-05-22 17:50:26 -070091 RTC_DEFINE_STATIC_LOCAL(const T, def, ());
andresp@webrtc.org6b68c282013-05-13 08:06:36 +000092 return def;
93 }
94
95 typedef std::map<OptionIdentifier, BaseOption*> OptionMap;
96 OptionMap options_;
97
98 // DISALLOW_COPY_AND_ASSIGN
99 Config(const Config&);
100 void operator=(const Config&);
101};
102
103template<typename T>
104const 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
115template<typename T>
116void Config::Set(T* value) {
117 BaseOption*& it = options_[identifier<T>()];
118 delete it;
119 it = new Option<T>(value);
120}
andrew@webrtc.org61e596f2013-07-25 18:28:29 +0000121
andresp@webrtc.org6b68c282013-05-13 08:06:36 +0000122} // namespace webrtc
andrew@webrtc.org61e596f2013-07-25 18:28:29 +0000123
124#endif // WEBRTC_COMMON_H_