Improve QueueAppender/IOBufQueue performance
[folly.git] / folly / DynamicConverter.h
index e73c19c21fa53aeba17de2add3374f147b80a820..55c9b2e591605e5dea4052a9aeeab29c9d061cb5 100644 (file)
 #include <boost/mpl/has_xxx.hpp>
 
 #include <folly/Likely.h>
+#include <folly/Optional.h>
 #include <folly/Traits.h>
 #include <folly/dynamic.h>
 
 namespace folly {
-  template <typename T> T convertTo(const dynamic&);
-  template <typename T> dynamic toDynamic(const T&);
-}
+template <typename T>
+T convertTo(const dynamic&);
+template <typename T>
+dynamic toDynamic(const T&);
+} // namespace folly
 
 /**
  * convertTo returns a well-typed representation of the input dynamic.
@@ -99,31 +102,35 @@ using is_associative = StrictConjunction<is_range<T>, has_key_type<T>>;
 
 namespace dynamicconverter_detail {
 
-template<typename T>
+template <typename T>
 struct Dereferencer {
   static inline void derefToCache(
-      T* /* mem */, const dynamic::const_item_iterator& /* it */) {
+      Optional<T>* /* mem */,
+      const dynamic::const_item_iterator& /* it */) {
     throw TypeError("array", dynamic::Type::OBJECT);
   }
 
-  static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
-    new (mem) T(convertTo<T>(*it));
+  static inline void derefToCache(
+      Optional<T>* mem,
+      const dynamic::const_iterator& it) {
+    mem->emplace(convertTo<T>(*it));
   }
 };
 
-template<typename F, typename S>
+template <typename F, typename S>
 struct Dereferencer<std::pair<F, S>> {
-  static inline void
-  derefToCache(std::pair<F, S>* mem, const dynamic::const_item_iterator& it) {
-    new (mem) std::pair<F, S>(
-        convertTo<F>(it->first), convertTo<S>(it->second)
-    );
+  static inline void derefToCache(
+      Optional<std::pair<F, S>>* mem,
+      const dynamic::const_item_iterator& it) {
+    mem->emplace(convertTo<F>(it->first), convertTo<S>(it->second));
   }
 
   // Intentional duplication of the code in Dereferencer
   template <typename T>
-  static inline void derefToCache(T* mem, const dynamic::const_iterator& it) {
-    new (mem) T(convertTo<T>(*it));
+  static inline void derefToCache(
+      Optional<T>* mem,
+      const dynamic::const_iterator& it) {
+    mem->emplace(convertTo<T>(*it));
   }
 };
 
@@ -135,26 +142,22 @@ class Transformer
 
   typedef typename T::value_type ttype;
 
-  mutable ttype cache_;
-  mutable bool valid_;
+  mutable Optional<ttype> cache_;
 
   void increment() {
     ++this->base_reference();
-    valid_ = false;
+    cache_ = none;
   }
 
   ttype& dereference() const {
-    if (LIKELY(!valid_)) {
-      cache_.~ttype();
+    if (!cache_) {
       Dereferencer<ttype>::derefToCache(&cache_, this->base_reference());
-      valid_ = true;
     }
-    return cache_;
+    return cache_.value();
   }
 
  public:
-  explicit Transformer(const It& it)
-      : Transformer::iterator_adaptor_(it), valid_(false) {}
+  explicit Transformer(const It& it) : Transformer::iterator_adaptor_(it) {}
 };
 
 // conversion factory
@@ -355,7 +358,7 @@ struct DynamicConstructor<
 };
 
 // pair
-template<typename A, typename B>
+template <typename A, typename B>
 struct DynamicConstructor<std::pair<A, B>, void> {
   static dynamic construct(const std::pair<A, B>& x) {
     dynamic d = dynamic::array;
@@ -373,7 +376,7 @@ T convertTo(const dynamic& d) {
   return DynamicConverter<typename std::remove_cv<T>::type>::convert(d);
 }
 
-template<typename T>
+template <typename T>
 dynamic toDynamic(const T& x) {
   return DynamicConstructor<typename std::remove_cv<T>::type>::construct(x);
 }