eo-cxx: Add promise type
This commit is contained in:
parent
e0b444f95f
commit
3339f03964
|
@ -1,5 +1,5 @@
|
|||
///
|
||||
/// @file eo_concrete.hh
|
||||
/// @file eo_promise.hh
|
||||
///
|
||||
|
||||
#ifndef EFL_CXX_EO_PROMISE_HH
|
||||
|
@ -14,271 +14,13 @@
|
|||
#include <condition_variable>
|
||||
|
||||
#include <eina_tuple.hh>
|
||||
#include <eo_promise_meta.hh>
|
||||
|
||||
namespace efl {
|
||||
|
||||
template <typename...Args>
|
||||
struct shared_future;
|
||||
|
||||
namespace _impl {
|
||||
|
||||
template <typename...Futures>
|
||||
struct all_result_type;
|
||||
|
||||
template <typename...Args>
|
||||
struct all_result_type<shared_future<Args...>>
|
||||
{
|
||||
typedef shared_future<Args...> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2>
|
||||
struct all_result_type<shared_future<Args1...>, shared_future<Args2...>>
|
||||
{
|
||||
typedef shared_future<Args1..., Args2...> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2, typename...OtherFutures>
|
||||
struct all_result_type<shared_future<Args1...>, shared_future<Args2...>, OtherFutures...>
|
||||
{
|
||||
typedef typename all_result_type<shared_future<Args1..., Args2...>, OtherFutures...>::type type;
|
||||
};
|
||||
|
||||
template <typename...Futures>
|
||||
typename all_result_type<Futures...>::type
|
||||
all_impl(Futures const& ... futures)
|
||||
{
|
||||
Efl_Future* future = ::efl_future_all_internal(futures.native_handle()..., NULL);
|
||||
return typename all_result_type<Futures...>::type{ ::efl_ref(future)};
|
||||
}
|
||||
|
||||
template <typename...Futures>
|
||||
struct race_result_type;
|
||||
|
||||
template <typename...Args>
|
||||
struct race_result_type<shared_future<Args...>>
|
||||
{
|
||||
typedef shared_future<Args...> type;
|
||||
};
|
||||
|
||||
template <typename T, typename...Args>
|
||||
struct race_compose_impl;
|
||||
|
||||
template <typename T, typename A0, typename...Args>
|
||||
struct race_compose_impl<T, A0, Args...>
|
||||
{
|
||||
typedef typename std::conditional<eina::_mpl::tuple_contains<A0, T>::value
|
||||
, typename race_compose_impl<T, Args...>::type
|
||||
, typename race_compose_impl<typename eina::_mpl::push_back<T, A0>::type, Args...>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct race_compose_impl<T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct variant_from_tuple;
|
||||
|
||||
template <typename...Args>
|
||||
struct variant_from_tuple<std::tuple<Args...>>
|
||||
{
|
||||
typedef eina::variant<Args...> type;
|
||||
};
|
||||
|
||||
template <typename...Args>
|
||||
struct race_variant
|
||||
{
|
||||
typedef typename variant_from_tuple<typename race_compose_impl<std::tuple<>, Args...>::type>::type type;
|
||||
};
|
||||
|
||||
template <typename A0>
|
||||
struct race_result_type<shared_future<A0>>
|
||||
{
|
||||
typedef shared_future<A0> type;
|
||||
};
|
||||
|
||||
template <typename A0>
|
||||
struct race_result_type<shared_future<eina::variant<A0>>>
|
||||
{
|
||||
typedef shared_future<A0> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2>
|
||||
struct race_result_type<shared_future<Args1...>, shared_future<Args2...>>
|
||||
{
|
||||
typedef typename race_result_type<shared_future<typename race_variant<Args1..., Args2...>::type>>::type type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2, typename...OtherFutures>
|
||||
struct race_result_type<shared_future<Args1...>, shared_future<Args2...>, OtherFutures...>
|
||||
{
|
||||
typedef typename race_result_type<shared_future<typename race_variant<Args1..., Args2...>::type>
|
||||
, OtherFutures...>::type type;
|
||||
};
|
||||
|
||||
template <typename...Futures>
|
||||
typename race_result_type<Futures...>::type
|
||||
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
|
||||
<
|
||||
!std::is_same<A0, void>::value
|
||||
&& !std::is_same<typename std::result_of<F(A0)>::type, void>::value
|
||||
>::type
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
typename std::aligned_storage<sizeof(A0), alignof(A0)>::type storage;
|
||||
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;
|
||||
c_type* c_value = eina::alloc_to_c_traits<result_type>::copy_alloc(r);
|
||||
efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits<result_type>::free_alloc);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename A0, typename F>
|
||||
typename std::enable_if<std::is_same<A0, void>::value>::type
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t N, typename...Args, typename...StorageArgs>
|
||||
static void future_invoke_impl_read_accessor
|
||||
(Eina_Accessor*, std::tuple<StorageArgs...>&, std::tuple<Args...>*, std::true_type)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t N, typename...Args, typename...StorageArgs>
|
||||
static void future_invoke_impl_read_accessor
|
||||
(Eina_Accessor* accessor
|
||||
, std::tuple<StorageArgs...>& storage_tuple
|
||||
, std::tuple<Args...>* args
|
||||
, std::false_type)
|
||||
{
|
||||
typedef std::tuple<Args...> tuple_type;
|
||||
typedef typename std::tuple_element<N, tuple_type>::type type;
|
||||
void* value;
|
||||
if(eina_accessor_data_get(accessor, N, &value))
|
||||
{
|
||||
eina::copy_from_c_traits<type>::copy_to_unitialized
|
||||
(static_cast<type*>(static_cast<void*>(&std::get<N>(storage_tuple))), value);
|
||||
|
||||
_impl::future_invoke_impl_read_accessor<N+1>
|
||||
(accessor, storage_tuple, args
|
||||
, std::integral_constant<bool, (N+1 == sizeof...(Args))>());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::abort();
|
||||
// some error
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename...Args, std::size_t...I>
|
||||
void future_invoke_impl(F f, Efl_Event const* event, std::tuple<Args...>* arguments_dummy, eina::index_sequence<I...>)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
typedef std::tuple<Args...> arguments;
|
||||
typedef std::tuple<typename std::aligned_storage<sizeof(Args), alignof(Args)>::type...>
|
||||
storage_tuple_type;
|
||||
storage_tuple_type storage_tuple;
|
||||
|
||||
future_invoke_impl_read_accessor<0ul>
|
||||
(static_cast<Eina_Accessor*>(info->value)
|
||||
, storage_tuple
|
||||
, arguments_dummy, std::false_type{});
|
||||
|
||||
auto r = f(*static_cast<typename std::tuple_element<I, arguments>::type*>
|
||||
(static_cast<void*>(&std::get<I>(storage_tuple)))...);
|
||||
|
||||
typedef decltype(r) result_type;
|
||||
typedef typename eina::alloc_to_c_traits<result_type>::c_type c_type;
|
||||
c_type* c_value = eina::alloc_to_c_traits<result_type>::copy_alloc(r);
|
||||
efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits<result_type>::free_alloc);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename...OtherArgs, typename F>
|
||||
void
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
std::tuple<A0, A1, OtherArgs...>* p = nullptr;
|
||||
_impl::future_invoke_impl(f, event, p, eina::make_index_sequence<sizeof...(OtherArgs) + 2>{});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct progress;
|
||||
|
||||
|
@ -609,13 +351,119 @@ race(shared_future<Args1...> future1, shared_future<Args2...> future2, Futures..
|
|||
{
|
||||
return _impl::race_impl(future1, future2, futures...);
|
||||
}
|
||||
|
||||
template <typename...Args>
|
||||
struct promise
|
||||
|
||||
namespace _impl {
|
||||
|
||||
struct promise_common
|
||||
{
|
||||
explicit promise_common(Efl_Promise* _promise) : _promise(_promise) {}
|
||||
explicit promise_common(std::nullptr_t) : _promise(nullptr) {}
|
||||
promise_common()
|
||||
{
|
||||
_promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
|
||||
}
|
||||
~promise_common()
|
||||
{
|
||||
if(_promise)
|
||||
::efl_unref(_promise);
|
||||
}
|
||||
promise_common(promise_common const& other)
|
||||
: _promise( ::efl_ref(other._promise))
|
||||
{
|
||||
}
|
||||
promise_common(promise_common&& other)
|
||||
: _promise(nullptr)
|
||||
{
|
||||
std::swap(*this, other);
|
||||
}
|
||||
promise_common& operator=(promise_common const& other)
|
||||
{
|
||||
_promise = ::efl_ref(other._promise);
|
||||
return *this;
|
||||
}
|
||||
promise_common& operator=(promise_common&& other)
|
||||
{
|
||||
std::swap(*this, other);
|
||||
return *this;
|
||||
}
|
||||
bool valid() const
|
||||
{
|
||||
return _promise != nullptr;
|
||||
}
|
||||
void swap(promise_common& other)
|
||||
{
|
||||
std::swap(*this, other);
|
||||
}
|
||||
void set_exception(std::exception_ptr /*p*/)
|
||||
{
|
||||
}
|
||||
|
||||
Efl_Promise* _promise;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct promise_1_type : promise_common
|
||||
{
|
||||
typedef promise_common _base_type;
|
||||
using _base_type::_base_type;
|
||||
using _base_type::swap;
|
||||
using _base_type::set_exception;
|
||||
|
||||
void set_value(T const& v)
|
||||
{
|
||||
typedef typename eina::alloc_to_c_traits<T>::c_type c_type;
|
||||
c_type* c_value = eina::alloc_to_c_traits<T>::copy_alloc(v);
|
||||
efl_promise_value_set(this->_promise, c_value, & eina::alloc_to_c_traits<T>::free_alloc);
|
||||
}
|
||||
void set_value(T&& v)
|
||||
{
|
||||
typedef typename eina::alloc_to_c_traits<T>::c_type c_type;
|
||||
c_type* c_value = eina::alloc_to_c_traits<T>::copy_alloc(std::move(v));
|
||||
efl_promise_value_set(this->_promise, c_value, & eina::alloc_to_c_traits<T>::free_alloc);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct promise_1_type<void> : promise_common
|
||||
{
|
||||
typedef promise_common _base_type;
|
||||
using _base_type::_base_type;
|
||||
using _base_type::swap;
|
||||
using _base_type::set_exception;
|
||||
|
||||
void set_value()
|
||||
{
|
||||
efl_promise_value_set(this->_promise, nullptr, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T, typename Progress = void>
|
||||
struct promise : private _impl::promise_1_type<T>
|
||||
{
|
||||
typedef _impl::promise_1_type<T> _base_type;
|
||||
using _base_type::_base_type;
|
||||
using _base_type::set_value;
|
||||
using _base_type::set_exception;
|
||||
|
||||
shared_future<T> get_future()
|
||||
{
|
||||
return shared_future<T>{ ::efl_ref( ::efl_promise_future_get(this->_promise)) };
|
||||
}
|
||||
|
||||
void swap(promise<T>& other)
|
||||
{
|
||||
_base_type::swap(other);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename...Args>
|
||||
void swap(promise<Args...>& lhs, promise<Args...>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
///
|
||||
/// @file eo_promise_meta.hh
|
||||
///
|
||||
|
||||
#ifndef EFL_CXX_EO_PROMISE_META_HH
|
||||
#define EFL_CXX_EO_PROMISE_META_HH
|
||||
|
||||
namespace efl {
|
||||
|
||||
template <typename...Args>
|
||||
struct shared_future;
|
||||
|
||||
namespace _impl {
|
||||
|
||||
template <typename...Futures>
|
||||
struct all_result_type;
|
||||
|
||||
template <typename...Args>
|
||||
struct all_result_type<shared_future<Args...>>
|
||||
{
|
||||
typedef shared_future<Args...> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2>
|
||||
struct all_result_type<shared_future<Args1...>, shared_future<Args2...>>
|
||||
{
|
||||
typedef shared_future<Args1..., Args2...> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2, typename...OtherFutures>
|
||||
struct all_result_type<shared_future<Args1...>, shared_future<Args2...>, OtherFutures...>
|
||||
{
|
||||
typedef typename all_result_type<shared_future<Args1..., Args2...>, OtherFutures...>::type type;
|
||||
};
|
||||
|
||||
template <typename...Futures>
|
||||
typename all_result_type<Futures...>::type
|
||||
all_impl(Futures const& ... futures)
|
||||
{
|
||||
Efl_Future* future = ::efl_future_all_internal(futures.native_handle()..., NULL);
|
||||
return typename all_result_type<Futures...>::type{ ::efl_ref(future)};
|
||||
}
|
||||
|
||||
template <typename...Futures>
|
||||
struct race_result_type;
|
||||
|
||||
template <typename...Args>
|
||||
struct race_result_type<shared_future<Args...>>
|
||||
{
|
||||
typedef shared_future<Args...> type;
|
||||
};
|
||||
|
||||
template <typename T, typename...Args>
|
||||
struct race_compose_impl;
|
||||
|
||||
template <typename T, typename A0, typename...Args>
|
||||
struct race_compose_impl<T, A0, Args...>
|
||||
{
|
||||
typedef typename std::conditional<eina::_mpl::tuple_contains<A0, T>::value
|
||||
, typename race_compose_impl<T, Args...>::type
|
||||
, typename race_compose_impl<typename eina::_mpl::push_back<T, A0>::type, Args...>::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct race_compose_impl<T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct variant_from_tuple;
|
||||
|
||||
template <typename...Args>
|
||||
struct variant_from_tuple<std::tuple<Args...>>
|
||||
{
|
||||
typedef eina::variant<Args...> type;
|
||||
};
|
||||
|
||||
template <typename...Args>
|
||||
struct race_variant
|
||||
{
|
||||
typedef typename variant_from_tuple<typename race_compose_impl<std::tuple<>, Args...>::type>::type type;
|
||||
};
|
||||
|
||||
template <typename A0>
|
||||
struct race_result_type<shared_future<A0>>
|
||||
{
|
||||
typedef shared_future<A0> type;
|
||||
};
|
||||
|
||||
template <typename A0>
|
||||
struct race_result_type<shared_future<eina::variant<A0>>>
|
||||
{
|
||||
typedef shared_future<A0> type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2>
|
||||
struct race_result_type<shared_future<Args1...>, shared_future<Args2...>>
|
||||
{
|
||||
typedef typename race_result_type<shared_future<typename race_variant<Args1..., Args2...>::type>>::type type;
|
||||
};
|
||||
|
||||
template <typename...Args1, typename...Args2, typename...OtherFutures>
|
||||
struct race_result_type<shared_future<Args1...>, shared_future<Args2...>, OtherFutures...>
|
||||
{
|
||||
typedef typename race_result_type<shared_future<typename race_variant<Args1..., Args2...>::type>
|
||||
, OtherFutures...>::type type;
|
||||
};
|
||||
|
||||
template <typename...Futures>
|
||||
typename race_result_type<Futures...>::type
|
||||
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
|
||||
<
|
||||
!std::is_same<A0, void>::value
|
||||
&& !std::is_same<typename std::result_of<F(A0)>::type, void>::value
|
||||
>::type
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
typename std::aligned_storage<sizeof(A0), alignof(A0)>::type storage;
|
||||
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;
|
||||
c_type* c_value = eina::alloc_to_c_traits<result_type>::copy_alloc(r);
|
||||
efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits<result_type>::free_alloc);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename A0, typename F>
|
||||
typename std::enable_if<std::is_same<A0, void>::value>::type
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
f();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t N, typename...Args, typename...StorageArgs>
|
||||
static void future_invoke_impl_read_accessor
|
||||
(Eina_Accessor*, std::tuple<StorageArgs...>&, std::tuple<Args...>*, std::true_type)
|
||||
{
|
||||
}
|
||||
|
||||
template <std::size_t N, typename...Args, typename...StorageArgs>
|
||||
static void future_invoke_impl_read_accessor
|
||||
(Eina_Accessor* accessor
|
||||
, std::tuple<StorageArgs...>& storage_tuple
|
||||
, std::tuple<Args...>* args
|
||||
, std::false_type)
|
||||
{
|
||||
typedef std::tuple<Args...> tuple_type;
|
||||
typedef typename std::tuple_element<N, tuple_type>::type type;
|
||||
void* value;
|
||||
if(eina_accessor_data_get(accessor, N, &value))
|
||||
{
|
||||
eina::copy_from_c_traits<type>::copy_to_unitialized
|
||||
(static_cast<type*>(static_cast<void*>(&std::get<N>(storage_tuple))), value);
|
||||
|
||||
_impl::future_invoke_impl_read_accessor<N+1>
|
||||
(accessor, storage_tuple, args
|
||||
, std::integral_constant<bool, (N+1 == sizeof...(Args))>());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::abort();
|
||||
// some error
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename...Args, std::size_t...I>
|
||||
void future_invoke_impl(F f, Efl_Event const* event, std::tuple<Args...>* arguments_dummy, eina::index_sequence<I...>)
|
||||
{
|
||||
Efl_Future_Event_Success* info = static_cast<Efl_Future_Event_Success*>(event->info);
|
||||
try
|
||||
{
|
||||
typedef std::tuple<Args...> arguments;
|
||||
typedef std::tuple<typename std::aligned_storage<sizeof(Args), alignof(Args)>::type...>
|
||||
storage_tuple_type;
|
||||
storage_tuple_type storage_tuple;
|
||||
|
||||
future_invoke_impl_read_accessor<0ul>
|
||||
(static_cast<Eina_Accessor*>(info->value)
|
||||
, storage_tuple
|
||||
, arguments_dummy, std::false_type{});
|
||||
|
||||
auto r = f(*static_cast<typename std::tuple_element<I, arguments>::type*>
|
||||
(static_cast<void*>(&std::get<I>(storage_tuple)))...);
|
||||
|
||||
typedef decltype(r) result_type;
|
||||
typedef typename eina::alloc_to_c_traits<result_type>::c_type c_type;
|
||||
c_type* c_value = eina::alloc_to_c_traits<result_type>::copy_alloc(r);
|
||||
efl_promise_value_set(info->next, c_value, & eina::alloc_to_c_traits<result_type>::free_alloc);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
template <typename A0, typename A1, typename...OtherArgs, typename F>
|
||||
void
|
||||
future_invoke(F f, Efl_Event const* event)
|
||||
{
|
||||
std::tuple<A0, A1, OtherArgs...>* p = nullptr;
|
||||
_impl::future_invoke_impl(f, event, p, eina::make_index_sequence<sizeof...(OtherArgs) + 2>{});
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
|
@ -867,6 +867,68 @@ START_TEST(eo_cxx_future_race_variant_then_value)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
template <typename...Args>
|
||||
void eo_cxx_promise_construct_and_destroy_impl()
|
||||
{
|
||||
ecore_init();
|
||||
|
||||
{
|
||||
efl::promise<Args...> promise;
|
||||
efl::shared_future<Args...> f = promise.get_future();
|
||||
}
|
||||
ecore_shutdown();
|
||||
}
|
||||
|
||||
START_TEST(eo_cxx_promise_construct_and_destroy)
|
||||
{
|
||||
eo_cxx_promise_construct_and_destroy_impl<int>();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
template <typename T>
|
||||
struct test_value_get;
|
||||
|
||||
template <>
|
||||
struct test_value_get<int>
|
||||
{
|
||||
static int get() { return 5; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void eo_cxx_promise_value_set_impl()
|
||||
{
|
||||
ecore_init();
|
||||
|
||||
{
|
||||
efl::promise<T> promise;
|
||||
efl::shared_future<T> f = promise.get_future();
|
||||
|
||||
std::thread thread
|
||||
([&] {
|
||||
efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start
|
||||
efl::ecore::main_loop_thread_safe_call_async
|
||||
([&]
|
||||
{
|
||||
promise.set_value(test_value_get<T>::get());
|
||||
});
|
||||
|
||||
T value = f.get();
|
||||
ck_assert_int_eq(value, test_value_get<T>::get());
|
||||
efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); });
|
||||
});
|
||||
|
||||
ecore_main_loop_begin();
|
||||
|
||||
thread.join();
|
||||
}
|
||||
ecore_shutdown();
|
||||
}
|
||||
|
||||
START_TEST(eo_cxx_promise_value_set)
|
||||
{
|
||||
eo_cxx_promise_value_set_impl<int>();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
eo_cxx_test_promise(TCase* tc)
|
||||
|
@ -893,4 +955,7 @@ eo_cxx_test_promise(TCase* tc)
|
|||
|
||||
tcase_add_test(tc, eo_cxx_future_race_variant_get);
|
||||
tcase_add_test(tc, eo_cxx_future_race_variant_then_value);
|
||||
|
||||
tcase_add_test(tc, eo_cxx_promise_construct_and_destroy);
|
||||
tcase_add_test(tc, eo_cxx_promise_value_set);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue