eo-cxx: Add race promises through eina::variant
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Wed, 17 Aug 2016 02:26:52 +0000 (23:26 -0300)
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Wed, 14 Sep 2016 03:33:22 +0000 (00:33 -0300)
src/bindings/cxx/eina_cxx/eina_copy_traits.hh
src/bindings/cxx/eo_cxx/eo_promise.hh

index 0db8bd8..e6e0164 100644 (file)
@@ -7,6 +7,15 @@
 
 namespace efl { namespace eina {
 
+namespace _impl {
+template<bool...> struct bool_pack;
+template <bool...Args>
+struct and_ : std::is_same<bool_pack<Args..., true>, bool_pack<true, Args...>> {};
+}
+    
+template <typename... Args>
+struct variant;
+
 template <typename T, typename Enable = void>
 struct copy_from_c_traits;
 
@@ -19,6 +28,18 @@ struct copy_from_c_traits<T, typename std::enable_if<std::is_fundamental<T>::val
   }
 };
 
+template <typename...Args>
+struct copy_from_c_traits<eina::variant<Args...>,
+                          typename std::enable_if<_impl::and_<std::is_fundamental<Args>::value...>::value>::type>
+{
+  template <typename T>
+  static void copy_to_unitialized(eina::variant<Args...>* storage, T const* data)
+  {
+     new (storage) eina::variant<Args...>{*data};
+  }
+};
+    
+    
 template <typename T, typename Enable = void>
 struct alloc_to_c_traits;
 
@@ -37,7 +58,7 @@ struct alloc_to_c_traits<T, typename std::enable_if<std::is_fundamental<T>::valu
     ::free(data);
   }
 };
-    
+
 } }
 
 #endif
index f9a3261..7c3741a 100644 (file)
@@ -125,6 +125,50 @@ race_impl(Futures const& ... futures)
   Efl_Future* future = ::efl_future_race_internal(futures.native_handle()..., NULL);
   return typename race_result_type<Futures...>::type{ ::efl_ref(future)};
 }
+
+template <typename T, typename Enabler = void>
+struct future_copy_traits
+{
+   static void copy(T* storage, Efl_Future_Event_Success const* info)
+   {
+      eina::copy_from_c_traits<T>::copy_to_unitialized
+        (storage, info->value);
+   }
+};
+
+template <typename...Args>
+struct future_copy_traits<eina::variant<Args...>>
+{
+   template <std::size_t I>
+   static void copy_impl(eina::variant<Args...>*, void const*, int, std::integral_constant<std::size_t, I>
+                         , std::integral_constant<std::size_t, I>)
+   {
+     std::abort();
+   }
+
+   template <std::size_t I, std::size_t N>
+   static void copy_impl(eina::variant<Args...>* storage, void const* value, int index, std::integral_constant<std::size_t, I>
+                         , std::integral_constant<std::size_t, N> max
+                         , typename std::enable_if<I != N>::type* = 0)
+   {
+     if(I == index)
+       {
+         eina::copy_from_c_traits<eina::variant<Args...>>::copy_to_unitialized
+           (storage, static_cast<typename std::tuple_element<I, std::tuple<Args...>>::type const*>
+            (static_cast<void const*>(value)));
+       }
+     else
+       copy_impl(storage, value, index, std::integral_constant<std::size_t, I+1>{}, max);
+   }
+   
+   static void copy(eina::variant<Args...>* storage, Efl_Future_Event_Success const* other_info)
+   {
+      Efl_Future_Race_Success const* info = static_cast<Efl_Future_Race_Success const*>
+        (static_cast<void const*>(other_info));
+      copy_impl(storage, info->value, info->index, std::integral_constant<std::size_t, 0ul>{}
+                , std::integral_constant<std::size_t, sizeof...(Args)>{});
+   }
+};
   
 template <typename A0, typename F>
 typename std::enable_if
@@ -138,8 +182,7 @@ future_invoke(F f, Efl_Event const* event)
    try
      {
         typename std::aligned_storage<sizeof(A0), alignof(A0)>::type storage;
-        eina::copy_from_c_traits<A0>::copy_to_unitialized
-          (static_cast<A0*>(static_cast<void*>(&storage)), info->value);
+        future_copy_traits<A0>::copy(static_cast<A0*>(static_cast<void*>(&storage)), info);
         auto r = f(*static_cast<A0*>(static_cast<void*>(&storage)));
         typedef decltype(r) result_type;
         typedef typename eina::alloc_to_c_traits<result_type>::c_type c_type;
@@ -375,8 +418,7 @@ struct shared_future_1_type : private shared_future_common
       Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
 
       std::unique_lock<std::mutex> l(wait_state->mutex);
-      eina::copy_from_c_traits<T>::copy_to_unitialized
-        (static_cast<T*>(static_cast<void*>(&wait_state->storage)), info->value);
+      _impl::future_copy_traits<T>::copy(static_cast<T*>(static_cast<void*>(&wait_state->storage)), info);
       wait_state->available = true;
       wait_state->cv.notify_one();
    }