| /* | |
| * 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> | |
| #include "webrtc/base/basictypes.h" | |
| 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 too 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 set 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() { | |
| RTC_DEFINE_STATIC_LOCAL(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_ |