felipealmeida pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=10293e652055a5e741f3b9f87c14e7919bb2d267

commit 10293e652055a5e741f3b9f87c14e7919bb2d267
Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br>
Date:   Tue Sep 20 23:30:13 2016 -0300

    eo-cxx: Add progress to future and promise
---
 src/bindings/cxx/eo_cxx/eo_future.hh       | 199 +++++++++++++++++++++++++----
 src/bindings/cxx/eo_cxx/eo_promise.hh      | 121 ++++--------------
 src/bindings/cxx/eo_cxx/eo_promise_meta.hh |  44 +++++++
 src/tests/eo_cxx/eo_cxx_test_promise.cc    |  40 ++++++
 4 files changed, 285 insertions(+), 119 deletions(-)

diff --git a/src/bindings/cxx/eo_cxx/eo_future.hh 
b/src/bindings/cxx/eo_cxx/eo_future.hh
index 7154b5f..fbab965 100644
--- a/src/bindings/cxx/eo_cxx/eo_future.hh
+++ b/src/bindings/cxx/eo_cxx/eo_future.hh
@@ -116,17 +116,15 @@ struct shared_future_common
    Efl_Future* _future;
 };
   
-template <typename T>
-struct shared_future_1_type : private shared_future_common
+template <typename T, typename Progress = void>
+struct shared_future_1_type : shared_future_common
 {
    typedef shared_future_common _base_type;
 
    using _base_type::_base_type;
-   using _base_type::swap;
-   using _base_type::valid;
-   using _base_type::native_handle;
-   using _base_type::wait;
-   typedef _base_type::native_handle_type native_handle_type;
+   shared_future_1_type() = default;
+   shared_future_1_type(shared_future_common const& other)
+     : _base_type(other) {}
 
    T get() const
    {
@@ -162,20 +160,17 @@ struct shared_future_1_type : private shared_future_common
       wait_state->cv.notify_one();
    }
 
-   typedef shared_future_1_type<T> _self_type;
+   typedef shared_future_1_type<T, Progress> _self_type;
 };
 
 template <typename T>
-struct shared_race_future_1_type : private shared_future_common
+struct shared_race_future_1_type : shared_future_common
 {
    typedef shared_future_common _base_type;
 
    using _base_type::_base_type;
-   using _base_type::swap;
-   using _base_type::valid;
-   using _base_type::native_handle;
-   using _base_type::wait;
-   typedef _base_type::native_handle_type native_handle_type;
+   shared_race_future_1_type(_base_type const& other)
+     : _base_type(other) {}
 
    T get() const
    {
@@ -211,20 +206,18 @@ struct shared_race_future_1_type : private 
shared_future_common
       wait_state->cv.notify_one();
    }
 
-   typedef shared_future_1_type<T> _self_type;
+   typedef shared_race_future_1_type<T> _self_type;
 };
-  
+
 template <typename...Args>
-struct shared_future_varargs_type : private shared_future_common
+struct shared_future_varargs_type : shared_future_common
 {
    typedef shared_future_common _base_type;
 
    using _base_type::_base_type;
-   using _base_type::swap;
-   using _base_type::valid;
-   using _base_type::native_handle;
-   using _base_type::wait;
-   typedef _base_type::native_handle_type native_handle_type;
+   shared_future_varargs_type() = default;
+   shared_future_varargs_type(_base_type const& other)
+     : _base_type(other) {}
 
    typedef std::tuple<Args...> tuple_type;
 
@@ -314,17 +307,59 @@ struct shared_future_varargs_type : private 
shared_future_common
 }
 
 template <typename...Args>
-struct shared_future : private std::conditional<sizeof...(Args) == 1, 
_impl::shared_future_1_type<typename std::tuple_element<0u, 
std::tuple<Args...>>::type>, _impl::shared_future_varargs_type<Args...>>::type
+struct shared_future : private
+  std::conditional
+  <
+    sizeof...(Args) == 1
+    , _impl::shared_future_1_type<typename std::tuple_element<0u, 
std::tuple<Args...>>::type>
+    , typename std::conditional
+      <_impl::is_progress<typename std::tuple_element<sizeof...(Args) - 1, 
std::tuple<Args...>>::type>::value
+      , typename std::conditional
+        <sizeof...(Args) == 2
+        , _impl::shared_future_1_type<Args...>
+         , _impl::shared_future_varargs_type<Args...>
+         >::type
+       , _impl::shared_future_varargs_type<Args...>
+       >::type
+  >::type
 {
-   typedef typename std::conditional<sizeof...(Args) == 1, 
_impl::shared_future_1_type<typename std::tuple_element<0u, 
std::tuple<Args...>>::type>, _impl::shared_future_varargs_type<Args...>>::type 
_base_type;
-
+   typedef typename
+  std::conditional
+  <
+    sizeof...(Args) == 1
+    , _impl::shared_future_1_type<Args...>
+    , typename std::conditional
+      <_impl::is_progress<typename std::tuple_element<sizeof...(Args) - 1, 
std::tuple<Args...>>::type>::value
+      , typename std::conditional
+        <sizeof...(Args) == 2
+        , _impl::shared_future_1_type<Args...>
+         , _impl::shared_future_varargs_type<Args...>
+         >::type
+       , _impl::shared_future_varargs_type<Args...>
+       >::type
+  >::type
+     _base_type;
+   typedef typename _impl::progress_param<Args...>::type progress_param_type;
+   typedef typename _impl::progress_type<progress_param_type>::type 
progress_type;
+   typedef typename _base_type::native_handle_type native_handle_type;
    using _base_type::_base_type;
    using _base_type::swap;
    using _base_type::valid;
    using _base_type::get;
    using _base_type::wait;
    using _base_type::native_handle;
-   typedef typename _base_type::native_handle_type native_handle_type;
+
+   shared_future() = default;
+   template <typename...OtherArgs>
+   shared_future(shared_future<OtherArgs...> const& other
+                 , typename std::enable_if<_impl::is_progress_param_compatible
+                 <progress_param_type, typename 
_impl::progress_param<OtherArgs...>::type>::value>::type* = nullptr)
+     : _base_type(static_cast< _impl::shared_future_common const&>(other))
+   {
+   }
+
+   template <typename...OtherArgs>
+   friend struct shared_future;
 };
 
 template <typename...Args>
@@ -350,7 +385,119 @@ template <typename...Args>
 struct is_race_future<shared_race_future<Args...>> : std::true_type {};
 
 }
+
+template <template <typename...> class Future, typename...Args, typename F>
+typename std::enable_if
+<
+   !std::is_same<typename Future<Args...>::progress_type, void>::value
+>::type on_progress(Future<Args...> future, F function)
+{
+  struct private_data
+  {
+    F progress_cb;
+    Future<Args...> future;
+  };
+  private_data* pdata = new private_data
+    {std::move(function), std::move(future)};
+
+  typedef typename Future<Args...>::progress_type progress_type;
+  
+  Efl_Event_Cb raw_progress_cb =
+    [] (void* data, Efl_Event const* event)
+    {
+       private_data* pdata = static_cast<private_data*>(data);
+       try
+         {
+           Efl_Future_Event_Progress const* info = 
static_cast<Efl_Future_Event_Progress const*>(event->info);
+           pdata->progress_cb(*static_cast<progress_type 
const*>(info->progress));
+         }
+       catch(...)
+         {
+           // what should happen if progress_cb fails?
+         }
+    };
+  Efl_Event_Cb raw_delete_cb =
+    [] (void* data, Efl_Event const*)
+    {
+       private_data* pdata = static_cast<private_data*>(data);
+       delete pdata;
+    };
+
+  assert(pdata->future.valid());
+  efl_future_then(pdata->future.native_handle(), raw_delete_cb, raw_delete_cb, 
raw_progress_cb, pdata);
+}   
+
+template <template <typename...> class Future, typename...Args, typename 
Success, typename Error>
+shared_future
+<
+  typename std::enable_if
+  <
+    !std::is_same<void, typename std::tuple_element<0, 
std::tuple<Args...>>::type>::value
+    && !std::is_same<void, typename 
std::result_of<Success(Args...)>::type>::value
+    , typename std::result_of<Success(Args...)>::type
+  >::type
+> then(Future<Args...> future, Success success_cb, Error error_cb)
+{
+  struct private_data
+  {
+    Success success_cb;
+    Error error_cb;
+    Future<Args...> future;
+  };
+  private_data* pdata = new private_data
+    {std::move(success_cb), std::move(error_cb), std::move(future)};
+     
+  Efl_Event_Cb raw_success_cb =
+    [] (void* data, Efl_Event const* event)
+    {
+       private_data* pdata = static_cast<private_data*>(data);
+       try
+         {
+           _impl::future_invoke<Args...>(pdata->success_cb, event, 
_impl::is_race_future<Future<Args...>>{});
+           // should value_set the next promise
+         }
+       catch(...)
+         {
+           // should fail the next promise
+         }
+       delete pdata;
+    };
+  Efl_Event_Cb raw_error_cb =
+    [] (void* data, Efl_Event const* event)
+    {
+       private_data* pdata = static_cast<private_data*>(data);
+       Efl_Future_Event_Failure* info = 
static_cast<Efl_Future_Event_Failure*>(event->info);
+       pdata->error_cb(eina::error_code(info->error, 
eina::eina_error_category()));
+       // should error the next promise (or should the promise do that for me 
automatically?)
+       delete pdata;
+    };
+  
+      assert(pdata->future.valid());
+  Efl_Future* new_future
+    = efl_future_then(pdata->future.native_handle(), raw_success_cb, 
raw_error_cb, nullptr, pdata);
+  return shared_future<typename 
std::result_of<Success(Args...)>::type>{efl_ref(new_future)};
+}
   
+template <typename...Args, typename F>
+void then(shared_future<Args...> future, F function)
+{
+  
+}
+
+template <typename...Args1, typename...Args2, typename...Futures>
+typename _impl::all_result_type<shared_future<Args1...>, 
shared_future<Args2...>, Futures...>::type
+all(shared_future<Args1...> future1, shared_future<Args2...> future2, 
Futures...futures)
+{
+  return _impl::all_impl(future1, future2, futures...);
+}
+
+template <typename...Args1, typename...Args2, typename...Futures>
+typename _impl::race_result_type<shared_future<Args1...>, 
shared_future<Args2...>, Futures...>::type
+race(shared_future<Args1...> future1, shared_future<Args2...> future2, 
Futures...futures)
+{
+  return _impl::race_impl(future1, future2, futures...);
+}
+
 }
 
 #endif
diff --git a/src/bindings/cxx/eo_cxx/eo_promise.hh 
b/src/bindings/cxx/eo_cxx/eo_promise.hh
index f3b8714..943507f 100644
--- a/src/bindings/cxx/eo_cxx/eo_promise.hh
+++ b/src/bindings/cxx/eo_cxx/eo_promise.hh
@@ -22,80 +22,6 @@ namespace efl {
 template <typename...Args>
 struct shared_future;
   
-template <typename T>
-struct progress;
-
-template <template <typename...> class Future, typename...Args, typename 
Success, typename Error>
-shared_future
-<
-  typename std::enable_if
-  <
-    !std::is_same<void, typename std::tuple_element<0, 
std::tuple<Args...>>::type>::value
-    && !std::is_same<void, typename 
std::result_of<Success(Args...)>::type>::value
-    , typename std::result_of<Success(Args...)>::type
-  >::type
-> then(Future<Args...> future, Success success_cb, Error error_cb)
-{
-  struct private_data
-  {
-    Success success_cb;
-    Error error_cb;
-    Future<Args...> future;
-  };
-  private_data* pdata = new private_data
-    {std::move(success_cb), std::move(error_cb), std::move(future)};
-     
-  Efl_Event_Cb raw_success_cb =
-    [] (void* data, Efl_Event const* event)
-    {
-       private_data* pdata = static_cast<private_data*>(data);
-       try
-         {
-           _impl::future_invoke<Args...>(pdata->success_cb, event, 
_impl::is_race_future<Future<Args...>>{});
-           // should value_set the next promise
-         }
-       catch(...)
-         {
-           // should fail the next promise
-         }
-       delete pdata;
-    };
-  Efl_Event_Cb raw_error_cb =
-    [] (void* data, Efl_Event const* event)
-    {
-       private_data* pdata = static_cast<private_data*>(data);
-       Efl_Future_Event_Failure* info = 
static_cast<Efl_Future_Event_Failure*>(event->info);
-       pdata->error_cb(eina::error_code(info->error, 
eina::eina_error_category()));
-       // should error the next promise (or should the promise do that for me 
automatically?)
-       delete pdata;
-    };
-  
-      assert(pdata->future.valid());
-  Efl_Future* new_future
-    = efl_future_then(pdata->future.native_handle(), raw_success_cb, 
raw_error_cb, nullptr, pdata);
-  return shared_future<typename 
std::result_of<Success(Args...)>::type>{efl_ref(new_future)};
-}
-  
-template <typename...Args, typename F>
-void then(shared_future<Args...> future, F function)
-{
-  
-}
-
-template <typename...Args1, typename...Args2, typename...Futures>
-typename _impl::all_result_type<shared_future<Args1...>, 
shared_future<Args2...>, Futures...>::type
-all(shared_future<Args1...> future1, shared_future<Args2...> future2, 
Futures...futures)
-{
-  return _impl::all_impl(future1, future2, futures...);
-}
-
-template <typename...Args1, typename...Args2, typename...Futures>
-typename _impl::race_result_type<shared_future<Args1...>, 
shared_future<Args2...>, Futures...>::type
-race(shared_future<Args1...> future1, shared_future<Args2...> future2, 
Futures...futures)
-{
-  return _impl::race_impl(future1, future2, futures...);
-}
-
 namespace _impl {
 
 struct promise_common
@@ -144,15 +70,28 @@ struct promise_common
   
    Efl_Promise* _promise;
 };
-  
-template <typename T>
-struct promise_1_type : promise_common
+
+template <typename P>
+struct promise_progress : promise_common
 {
-   typedef promise_common _base_type;
-   using _base_type::_base_type;
-   using _base_type::swap;
-   using _base_type::set_exception;
+   void set_progress(P const& progress)
+   {
+      efl_promise_progress_set(this->_promise, &progress);
+   }
+};
+
+template <>
+struct promise_progress<void> : promise_common
+{
+   void set_progress()
+   {
+      efl_promise_progress_set(this->_promise, nullptr);
+   }
+};
   
+template <typename T, typename Progress>
+struct promise_1_type : promise_progress<Progress>
+{
    void set_value(T const& v)
    {
       typedef typename eina::alloc_to_c_traits<T>::c_type c_type;
@@ -167,14 +106,9 @@ struct promise_1_type : promise_common
    }
 };
 
-template <>
-struct promise_1_type<void> : promise_common
+template <typename Progress>
+struct promise_1_type<void, Progress> : promise_progress<Progress>
 {
-   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);
@@ -184,19 +118,20 @@ struct promise_1_type<void> : promise_common
 }
   
 template <typename T, typename Progress = void>
-struct promise : private _impl::promise_1_type<T>
+struct promise : private _impl::promise_1_type<T, Progress>
 {
-   typedef _impl::promise_1_type<T> _base_type;
+   typedef _impl::promise_1_type<T, Progress> _base_type;
    using _base_type::_base_type;
    using _base_type::set_value;
+   using _base_type::set_progress;
    using _base_type::set_exception;
 
-   shared_future<T> get_future()
+   shared_future<T, progress<Progress>> get_future()
    {
-      return shared_future<T>{ ::efl_ref( 
::efl_promise_future_get(this->_promise)) };
+      return shared_future<T, progress<Progress>>{ ::efl_ref( 
::efl_promise_future_get(this->_promise)) };
    }
 
-   void swap(promise<T>& other)
+   void swap(promise<T, progress<Progress>>& other)
    {
       _base_type::swap(other);
    }
diff --git a/src/bindings/cxx/eo_cxx/eo_promise_meta.hh 
b/src/bindings/cxx/eo_cxx/eo_promise_meta.hh
index 18b37d7..aa2894f 100644
--- a/src/bindings/cxx/eo_cxx/eo_promise_meta.hh
+++ b/src/bindings/cxx/eo_cxx/eo_promise_meta.hh
@@ -13,8 +13,52 @@ struct shared_future;
 template <typename...Args>
 struct shared_race_future;
 
+template <typename T>
+struct progress;
+  
 namespace _impl {
 
+template <typename T>
+struct is_progress : std::false_type {};
+
+template <typename T>
+struct is_progress<progress<T>> : std::true_type {};
+
+template <typename L, typename R>
+struct is_progress_param_compatible : std::false_type {};
+
+template <typename T>
+struct is_progress_param_compatible<T, T> : std::true_type {};
+  
+template <>
+struct is_progress_param_compatible<void, progress<void>> : std::true_type {};
+
+template <>
+struct is_progress_param_compatible<progress<void>, void> : std::true_type {};
+
+template <typename...Args>
+struct progress_param : std::conditional
+ <is_progress<typename std::tuple_element<sizeof...(Args) - 1, 
std::tuple<Args...>>::type>::value
+  , typename std::tuple_element<sizeof...(Args) - 1, std::tuple<Args...>>::type
+  , void>
+{
+};
+
+template <typename T>
+struct progress_type;
+
+template <typename T>
+struct progress_type<progress<T>>
+{
+  typedef T type;
+};
+
+template <>
+struct progress_type<void>
+{
+   typedef void type;
+};
+  
 template <typename...Futures>
 struct all_result_type;
 
diff --git a/src/tests/eo_cxx/eo_cxx_test_promise.cc 
b/src/tests/eo_cxx/eo_cxx_test_promise.cc
index 01b45c7..3edc5e8 100644
--- a/src/tests/eo_cxx/eo_cxx_test_promise.cc
+++ b/src/tests/eo_cxx/eo_cxx_test_promise.cc
@@ -930,6 +930,45 @@ START_TEST(eo_cxx_promise_value_set)
 }
 END_TEST
 
+template <typename T>
+void eo_cxx_promise_progress_set_impl()
+{
+   ecore_init();
+
+   {
+      efl::promise<int, T> promise;
+      efl::shared_future<int, efl::progress<T>> f = promise.get_future();
+
+      on_progress
+        (f, [&] (T const& value)
+         {
+            ck_assert_int_eq(value, test_value_get<T>::get());
+            ecore_main_loop_quit();
+         });
+      
+      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_progress(test_value_get<T>::get());
+             });
+        });
+
+      ecore_main_loop_begin();
+      
+      thread.join();
+   }
+   ecore_shutdown();
+}
+
+START_TEST(eo_cxx_promise_progress_set)
+{
+  eo_cxx_promise_progress_set_impl<int>();
+}
+END_TEST
+
 void
 eo_cxx_test_promise(TCase* tc)
 {
@@ -958,4 +997,5 @@ eo_cxx_test_promise(TCase* tc)
 
   tcase_add_test(tc, eo_cxx_promise_construct_and_destroy);
   tcase_add_test(tc, eo_cxx_promise_value_set);
+  tcase_add_test(tc, eo_cxx_promise_progress_set);
 }

-- 


Reply via email to