Home | History | Annotate | Download | only in webrtc
      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 #include "webrtc/base/basictypes.h"
     17 
     18 namespace webrtc {
     19 
     20 // Only add new values to the end of the enumeration and never remove (only
     21 // deprecate) to maintain binary compatibility.
     22 enum class ConfigOptionID {
     23   kMyExperimentForTest,
     24   kAlgo1CostFunctionForTest,
     25   kTemporalLayersFactory,
     26   kNetEqCapacityConfig,
     27   kNetEqFastAccelerate,
     28   kVoicePacing,
     29   kExtendedFilter,
     30   kDelayAgnostic,
     31   kExperimentalAgc,
     32   kExperimentalNs,
     33   kBeamforming,
     34   kIntelligibility
     35 };
     36 
     37 // Class Config is designed to ease passing a set of options across webrtc code.
     38 // Options are identified by typename in order to avoid incorrect casts.
     39 //
     40 // Usage:
     41 // * declaring an option:
     42 //    struct Algo1_CostFunction {
     43 //      virtual float cost(int x) const { return x; }
     44 //      virtual ~Algo1_CostFunction() {}
     45 //    };
     46 //
     47 // * accessing an option:
     48 //    config.Get<Algo1_CostFunction>().cost(value);
     49 //
     50 // * setting an option:
     51 //    struct SqrCost : Algo1_CostFunction {
     52 //      virtual float cost(int x) const { return x*x; }
     53 //    };
     54 //    config.Set<Algo1_CostFunction>(new SqrCost());
     55 //
     56 // Note: This class is thread-compatible (like STL containers).
     57 class Config {
     58  public:
     59   // Returns the option if set or a default constructed one.
     60   // Callers that access options too often are encouraged to cache the result.
     61   // Returned references are owned by this.
     62   //
     63   // Requires std::is_default_constructible<T>
     64   template<typename T> const T& Get() const;
     65 
     66   // Set the option, deleting any previous instance of the same.
     67   // This instance gets ownership of the newly set value.
     68   template<typename T> void Set(T* value);
     69 
     70   Config() {}
     71   ~Config() {
     72     // Note: this method is inline so webrtc public API depends only
     73     // on the headers.
     74     for (OptionMap::iterator it = options_.begin();
     75          it != options_.end(); ++it) {
     76       delete it->second;
     77     }
     78   }
     79 
     80  private:
     81   struct BaseOption {
     82     virtual ~BaseOption() {}
     83   };
     84 
     85   template<typename T>
     86   struct Option : BaseOption {
     87     explicit Option(T* v): value(v) {}
     88     ~Option() {
     89       delete value;
     90     }
     91     T* value;
     92   };
     93 
     94   template<typename T>
     95   static ConfigOptionID identifier() {
     96     return T::identifier;
     97   }
     98 
     99   // Used to instantiate a default constructed object that doesn't needs to be
    100   // owned. This allows Get<T> to be implemented without requiring explicitly
    101   // locks.
    102   template<typename T>
    103   static const T& default_value() {
    104     RTC_DEFINE_STATIC_LOCAL(const T, def, ());
    105     return def;
    106   }
    107 
    108   typedef std::map<ConfigOptionID, BaseOption*> OptionMap;
    109   OptionMap options_;
    110 
    111   // RTC_DISALLOW_COPY_AND_ASSIGN
    112   Config(const Config&);
    113   void operator=(const Config&);
    114 };
    115 
    116 template<typename T>
    117 const T& Config::Get() const {
    118   OptionMap::const_iterator it = options_.find(identifier<T>());
    119   if (it != options_.end()) {
    120     const T* t = static_cast<Option<T>*>(it->second)->value;
    121     if (t) {
    122       return *t;
    123     }
    124   }
    125   return default_value<T>();
    126 }
    127 
    128 template<typename T>
    129 void Config::Set(T* value) {
    130   BaseOption*& it = options_[identifier<T>()];
    131   delete it;
    132   it = new Option<T>(value);
    133 }
    134 
    135 }  // namespace webrtc
    136 
    137 #endif  // WEBRTC_COMMON_H_
    138