/// /// @file eo_promise_meta.hh /// #ifndef EFL_CXX_EO_PROMISE_META_HH #define EFL_CXX_EO_PROMISE_META_HH namespace efl { template struct shared_future; template struct shared_race_future; namespace _impl { template struct all_result_type; template struct all_result_type> { typedef shared_future type; }; template struct all_result_type, shared_future> { typedef shared_future type; }; template struct all_result_type, shared_future, OtherFutures...> { typedef typename all_result_type, OtherFutures...>::type type; }; template typename all_result_type::type all_impl(Futures const& ... futures) { Efl_Future* future = ::efl_future_all_internal(futures.native_handle()..., NULL); return typename all_result_type::type{ ::efl_ref(future)}; } template struct race_result_type; template struct race_result_type> { typedef shared_race_future type; }; template struct race_compose_impl; template struct race_compose_impl { typedef typename std::conditional::value , typename race_compose_impl::type , typename race_compose_impl::type, Args...>::type >::type type; }; template struct race_compose_impl { typedef T type; }; template struct variant_from_tuple; template struct variant_from_tuple> { typedef eina::variant type; }; template struct race_variant { typedef typename variant_from_tuple, Args...>::type>::type type; }; template struct race_result_type> { typedef shared_race_future type; }; template struct race_result_type>> { typedef shared_race_future type; }; template struct race_result_type, shared_future> { typedef typename race_result_type::type>>::type type; }; template struct race_result_type, shared_future, OtherFutures...> { typedef typename race_result_type::type> , OtherFutures...>::type type; }; template typename race_result_type::type race_impl(Futures const& ... futures) { Efl_Future* future = ::efl_future_race_internal(futures.native_handle()..., NULL); return typename race_result_type::type{ ::efl_ref(future)}; } template struct future_copy_traits { static void copy(T* storage, Efl_Future_Event_Success const* info) { eina::copy_from_c_traits::copy_to_unitialized (storage, info->value); } static void copy_race(T* storage, Efl_Future_Event_Success const* info) { Efl_Future_Race_Success const* race = static_cast(info->value); eina::copy_from_c_traits::copy_to_unitialized (storage, race->value); } }; template struct future_copy_traits> { template static void copy_impl(eina::variant*, void const*, int, std::integral_constant , std::integral_constant) { std::abort(); } template static void copy_impl(eina::variant* storage, void const* value, int index, std::integral_constant , std::integral_constant max , typename std::enable_if::type* = 0) { if(I == index) { eina::copy_from_c_traits>::copy_to_unitialized (storage, static_cast>::type const*> (static_cast(value))); } else copy_impl(storage, value, index, std::integral_constant{}, max); } static void copy(eina::variant*, Efl_Future_Event_Success const*) { std::abort(); } static void copy_race(eina::variant* storage, Efl_Future_Event_Success const* other_info) { Efl_Future_Race_Success const* info = static_cast (static_cast(other_info->value)); copy_impl(storage, info->value, info->index, std::integral_constant{} , std::integral_constant{}); } }; template typename std::enable_if < !std::is_same::value && !std::is_same::type, void>::value >::type future_invoke(F f, Efl_Event const* event, std::integral_constant /* is_race */) { Efl_Future_Event_Success* info = static_cast(event->info); try { typename std::aligned_storage::type storage; if(IsRace) future_copy_traits::copy_race(static_cast(static_cast(&storage)), info); else future_copy_traits::copy(static_cast(static_cast(&storage)), info); auto r = f(*static_cast(static_cast(&storage))); typedef decltype(r) result_type; typedef typename eina::alloc_to_c_traits::c_type c_type; c_type* c_value = eina::alloc_to_c_traits::copy_alloc(r); efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits::free_alloc); } catch(...) { } } template typename std::enable_if::value>::type future_invoke(F f, Efl_Event const* event, std::integral_constant) { Efl_Future_Event_Success* info = static_cast(event->info); try { f(); } catch(...) { } } template static void future_invoke_impl_read_accessor (Eina_Accessor*, std::tuple&, std::tuple*, std::true_type) { } template static void future_invoke_impl_read_accessor (Eina_Accessor* accessor , std::tuple& storage_tuple , std::tuple* args , std::false_type) { typedef std::tuple tuple_type; typedef typename std::tuple_element::type type; void* value; if(eina_accessor_data_get(accessor, N, &value)) { eina::copy_from_c_traits::copy_to_unitialized (static_cast(static_cast(&std::get(storage_tuple))), value); _impl::future_invoke_impl_read_accessor (accessor, storage_tuple, args , std::integral_constant()); } else { std::abort(); // some error } } template void future_invoke_impl(F f, Efl_Event const* event, std::tuple* arguments_dummy, std::integral_constant, eina::index_sequence) { Efl_Future_Event_Success* info = static_cast(event->info); try { typedef std::tuple arguments; typedef std::tuple::type...> storage_tuple_type; storage_tuple_type storage_tuple; future_invoke_impl_read_accessor<0ul> (static_cast(info->value) , storage_tuple , arguments_dummy, std::false_type{}); auto r = f(*static_cast::type*> (static_cast(&std::get(storage_tuple)))...); typedef decltype(r) result_type; typedef typename eina::alloc_to_c_traits::c_type c_type; c_type* c_value = eina::alloc_to_c_traits::copy_alloc(r); efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits::free_alloc); } catch(...) { } } template void future_invoke(F f, Efl_Event const* event, std::integral_constant race) { std::tuple* p = nullptr; _impl::future_invoke_impl(f, event, p, race, eina::make_index_sequence{}); } } } #endif