diff options
author | andresp@webrtc.org <andresp@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-05-13 08:06:36 +0000 |
---|---|---|
committer | andresp@webrtc.org <andresp@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> | 2013-05-13 08:06:36 +0000 |
commit | 1dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30a (patch) | |
tree | 30133647cbd14f0e843862760ace2db3fe650665 | |
parent | e56cf2c5803148f8e9b9c2d4a7f2154d0a976b61 (diff) | |
download | webrtc-1dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30a.tar.gz |
Added a config class to ease passing a set of options across webrtc.
Its main design reason is to expose control of experimental webrtc features.
R=niklas.enbom@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/1450009
git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@4004 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r-- | common.h | 120 | ||||
-rw-r--r-- | common_unittest.cc | 77 |
2 files changed, 197 insertions, 0 deletions
diff --git a/common.h b/common.h new file mode 100644 index 00000000..766f5b55 --- /dev/null +++ b/common.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_COMMON_H +#define WEBRTC_COMMON_H + +#include <map> + +namespace webrtc { + +// Class Config is designed to ease passing a set of options across webrtc code. +// Options are identified by typename in order to avoid incorrect casts. +// +// Usage: +// * declaring an option: +// struct Algo1_CostFunction { +// virtual float cost(int x) const { return x; } +// virtual ~Algo1_CostFunction() {} +// }; +// +// * accessing an option: +// config.Get<Algo1_CostFunction>().cost(value); +// +// * setting an option: +// struct SqrCost : Algo1_CostFunction { +// virtual float cost(int x) const { return x*x; } +// }; +// config.Set<Algo1_CostFunction>(new SqrCost()); +// +// Note: This class is thread-compatible (like STL containers). +class Config { + public: + // Returns the option if set or a default constructed one. + // Callers that access options to often are encouraged to cache the result. + // Returned references are owned by this. + // + // Requires std::is_default_constructible<T> + template<typename T> const T& Get() const; + + // Set the option, deleting any previous instance of the same. + // This instance gets ownership of the newly setted value. + template<typename T> void Set(T* value); + + Config() {} + ~Config() { + // Note: this method is inline so webrtc public API depends only + // on the headers. + for (OptionMap::iterator it = options_.begin(); + it != options_.end(); ++it) { + delete it->second; + } + } + + private: + typedef void* OptionIdentifier; + + struct BaseOption { + virtual ~BaseOption() {} + }; + + template<typename T> + struct Option : BaseOption { + explicit Option(T* v): value(v) {} + ~Option() { + delete value; + } + T* value; + }; + + // Own implementation of rtti-subset to avoid depending on rtti and its costs. + template<typename T> + static OptionIdentifier identifier() { + static char id_placeholder; + return &id_placeholder; + } + + // Used to instantiate a default constructed object that doesn't needs to be + // owned. This allows Get<T> to be implemented without requiring explicitly + // locks. + template<typename T> + static const T& default_value() { + static const T def; + return def; + } + + typedef std::map<OptionIdentifier, BaseOption*> OptionMap; + OptionMap options_; + + // DISALLOW_COPY_AND_ASSIGN + Config(const Config&); + void operator=(const Config&); +}; + +template<typename T> +const T& Config::Get() const { + OptionMap::const_iterator it = options_.find(identifier<T>()); + if (it != options_.end()) { + const T* t = static_cast<Option<T>*>(it->second)->value; + if (t) { + return *t; + } + } + return default_value<T>(); +} + +template<typename T> +void Config::Set(T* value) { + BaseOption*& it = options_[identifier<T>()]; + delete it; + it = new Option<T>(value); +} +} // namespace webrtc +#endif // WEBRTC_COMMON_H diff --git a/common_unittest.cc b/common_unittest.cc new file mode 100644 index 00000000..e672f1da --- /dev/null +++ b/common_unittest.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "common.h" // NOLINT + +#include "gtest/gtest.h" + +namespace webrtc { +namespace { + +struct MyExperiment { + enum { kDefaultFactor = 1 }; + enum { kDefaultOffset = 2 }; + + MyExperiment() + : factor(kDefaultFactor), offset(kDefaultOffset) {} + + MyExperiment(int factor, int offset) + : factor(factor), offset(offset) {} + + int factor; + int offset; +}; + +TEST(Config, ReturnsDefaultInstanceIfNotConfigured) { + Config config; + const MyExperiment& my_exp = config.Get<MyExperiment>(); + EXPECT_EQ(MyExperiment::kDefaultFactor, my_exp.factor); + EXPECT_EQ(MyExperiment::kDefaultOffset, my_exp.offset); +} + +TEST(Config, ReturnOptionWhenSet) { + Config config; + config.Set<MyExperiment>(new MyExperiment(5, 1)); + const MyExperiment& my_exp = config.Get<MyExperiment>(); + EXPECT_EQ(5, my_exp.factor); + EXPECT_EQ(1, my_exp.offset); +} + +TEST(Config, SetNullSetsTheOptionBackToDefault) { + Config config; + config.Set<MyExperiment>(new MyExperiment(5, 1)); + config.Set<MyExperiment>(NULL); + const MyExperiment& my_exp = config.Get<MyExperiment>(); + EXPECT_EQ(MyExperiment::kDefaultFactor, my_exp.factor); + EXPECT_EQ(MyExperiment::kDefaultOffset, my_exp.offset); +} + +struct Algo1_CostFunction { + Algo1_CostFunction() {} + + virtual int cost(int x) const { + return x; + } + + virtual ~Algo1_CostFunction() {} +}; + +struct SqrCost : Algo1_CostFunction { + virtual int cost(int x) const { + return x*x; + } +}; + +TEST(Config, SupportsPolimorphism) { + Config config; + config.Set<Algo1_CostFunction>(new SqrCost()); + EXPECT_EQ(25, config.Get<Algo1_CostFunction>().cost(5)); +} +} // namespace +} // namespace webrtc |