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 namespace 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).
     38 class Config {
     39  public:
     40   // Returns the option if set or a default constructed one.
     41   // Callers that access options too often are encouraged to cache the result.
     42   // 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.
     48   // This instance gets ownership of the newly set value.
     49   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 
    101 template<typename T>
    102 const 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 
    113 template<typename T>
    114 void Config::Set(T* value) {
    115   BaseOption*& it = options_[identifier<T>()];
    116   delete it;
    117   it = new Option<T>(value);
    118 }
    119 
    120 }  // namespace webrtc
    121 
    122 #endif  // WEBRTC_COMMON_H_
    123