11dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org/*
21dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
31dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *
41dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  Use of this source code is governed by a BSD-style license
51dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  that can be found in the LICENSE file in the root of the source
61dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  tree. An additional intellectual property rights grant can be found
71dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  in the file PATENTS.  All contributing project authors may
81dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
91dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org */
101dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
1125613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org#ifndef WEBRTC_COMMON_H_
1225613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org#define WEBRTC_COMMON_H_
131dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
141dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org#include <map>
151dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
161dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgnamespace webrtc {
171dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
181dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// Class Config is designed to ease passing a set of options across webrtc code.
191dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// Options are identified by typename in order to avoid incorrect casts.
201dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//
211dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// Usage:
221dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// * declaring an option:
231dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    struct Algo1_CostFunction {
241dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//      virtual float cost(int x) const { return x; }
251dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//      virtual ~Algo1_CostFunction() {}
261dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    };
271dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//
281dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// * accessing an option:
291dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    config.Get<Algo1_CostFunction>().cost(value);
301dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//
311dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// * setting an option:
321dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    struct SqrCost : Algo1_CostFunction {
331dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//      virtual float cost(int x) const { return x*x; }
341dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    };
351dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//    config.Set<Algo1_CostFunction>(new SqrCost());
361dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org//
371dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org// Note: This class is thread-compatible (like STL containers).
381dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgclass Config {
391dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org public:
401dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Returns the option if set or a default constructed one.
4125613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org  // Callers that access options too often are encouraged to cache the result.
421dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Returned references are owned by this.
431dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  //
441dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Requires std::is_default_constructible<T>
451dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  template<typename T> const T& Get() const;
461dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
471dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Set the option, deleting any previous instance of the same.
4825613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org  // This instance gets ownership of the newly set value.
491dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  template<typename T> void Set(T* value);
501dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
511dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  Config() {}
521dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  ~Config() {
531dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    // Note: this method is inline so webrtc public API depends only
541dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    // on the headers.
551dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    for (OptionMap::iterator it = options_.begin();
561dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org         it != options_.end(); ++it) {
571dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org      delete it->second;
581dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    }
591dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  }
601dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
611dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org private:
621dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  typedef void* OptionIdentifier;
631dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
641dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  struct BaseOption {
651dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    virtual ~BaseOption() {}
661dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  };
671dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
681dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  template<typename T>
691dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  struct Option : BaseOption {
701dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    explicit Option(T* v): value(v) {}
711dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    ~Option() {
721dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org      delete value;
731dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    }
741dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    T* value;
751dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  };
761dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
771dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Own implementation of rtti-subset to avoid depending on rtti and its costs.
781dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  template<typename T>
791dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  static OptionIdentifier identifier() {
801dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    static char id_placeholder;
811dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    return &id_placeholder;
821dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  }
831dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
841dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // Used to instantiate a default constructed object that doesn't needs to be
851dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // owned. This allows Get<T> to be implemented without requiring explicitly
861dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // locks.
871dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  template<typename T>
881dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  static const T& default_value() {
891dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    static const T def;
901dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    return def;
911dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  }
921dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
931dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  typedef std::map<OptionIdentifier, BaseOption*> OptionMap;
941dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  OptionMap options_;
951dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
961dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  // DISALLOW_COPY_AND_ASSIGN
971dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  Config(const Config&);
981dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  void operator=(const Config&);
991dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org};
1001dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
1011dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgtemplate<typename T>
1021dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgconst T& Config::Get() const {
1031dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  OptionMap::const_iterator it = options_.find(identifier<T>());
1041dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  if (it != options_.end()) {
1051dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    const T* t = static_cast<Option<T>*>(it->second)->value;
1061dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    if (t) {
1071dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org      return *t;
1081dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org    }
1091dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  }
1101dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  return default_value<T>();
1111dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org}
1121dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org
1131dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgtemplate<typename T>
1141dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.orgvoid Config::Set(T* value) {
1151dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  BaseOption*& it = options_[identifier<T>()];
1161dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  delete it;
1171dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org  it = new Option<T>(value);
1181dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org}
11925613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org
1201dba6218e85a206a8e57dc2c6d1e2f5a8cbbd30aandresp@webrtc.org}  // namespace webrtc
12125613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org
12225613ea5abb9c44acaab04519677f6d17fe5e306andrew@webrtc.org#endif  // WEBRTC_COMMON_H_
123