felipealmeida pushed a commit to branch master.

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

commit a63cfcafc7f8524dfad4e1bba763fb17c69d50e1
Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br>
Date:   Sun Aug 7 16:52:48 2016 -0300

    eolian-cxx: Implement future template class for C++
---
 src/Makefile_Cxx.am                                |  34 +-
 src/Makefile_Ecore.am                              |  13 +-
 src/Makefile_Eolian_Cxx.am                         |   4 +-
 src/bindings/cxx/ecore_cxx/Ecore.hh                | 164 +-------
 .../cxx/ecore_cxx/{Ecore.hh => Ecore_Manual.hh}    |  10 +-
 src/bindings/cxx/eina_cxx/Eina.hh                  |   1 +
 src/bindings/cxx/eina_cxx/eina_copy_traits.hh      |  43 +++
 src/bindings/cxx/eo_cxx/Eo.hh                      |   3 +-
 src/bindings/cxx/eo_cxx/eo_cxx_interop.hh          |  34 +-
 src/bindings/cxx/eo_cxx/eo_promise.hh              | 416 +++++++++++++++++++++
 src/lib/eolian_cxx/grammar/type_impl.hpp           |   8 +-
 src/tests/eo_cxx/eo_cxx_suite.cc                   |  27 ++
 src/tests/eo_cxx/eo_cxx_suite.h                    |  11 +
 src/tests/eo_cxx/eo_cxx_test_promise.cc            | 347 +++++++++++++++++
 14 files changed, 923 insertions(+), 192 deletions(-)

diff --git a/src/Makefile_Cxx.am b/src/Makefile_Cxx.am
index 2fda128..917d285 100644
--- a/src/Makefile_Cxx.am
+++ b/src/Makefile_Cxx.am
@@ -13,6 +13,7 @@ bindings/cxx/eo_cxx/Eo.hh \
 bindings/cxx/eo_cxx/eo_init.hh \
 bindings/cxx/eo_cxx/eo_ops.hh \
 bindings/cxx/eo_cxx/eo_wref.hh \
+bindings/cxx/eo_cxx/eo_promise.hh \
 bindings/cxx/eo_cxx/eo_private.hh
 
 ### Elementary C++
@@ -120,7 +121,8 @@ CLEANFILES += $(edje_eolian_cxx_hh) $(edje_eolian_cxx_impl) 
lib/edje/Edje.hh
 ### Ecore src/lib/ecore
 installed_ecorecxxheadersdir = $(includedir)/ecore-cxx-@VMAJ@
 dist_installed_ecorecxxheaders_DATA = \
-bindings/cxx/ecore_cxx/Ecore.hh
+bindings/cxx/ecore_cxx/Ecore.hh \
+bindings/cxx/ecore_cxx/Ecore_Manual.hh
 nodist_installed_ecorecxxheaders_DATA = $(ecore_eolian_cxx_hh) 
$(ecore_eolian_cxx_impl) \
 lib/ecore/Ecore.eo.hh
 
@@ -168,6 +170,7 @@ bindings/cxx/eina_cxx/eina_tuple_unwrap.hh \
 bindings/cxx/eina_cxx/eina_type_traits.hh \
 bindings/cxx/eina_cxx/eina_value.hh \
 bindings/cxx/eina_cxx/eina_workarounds.hh \
+bindings/cxx/eina_cxx/eina_copy_traits.hh \
 bindings/cxx/eina_cxx/Eina.hh
 
 ### Eio
@@ -186,9 +189,9 @@ CLEANFILES += $(eio_eolian_cxx_hh) $(eio_eolian_cxx_impl) 
lib/eio/Eio.hh
 
 if EFL_ENABLE_TESTS
 
-### Tests for Eina
-check_PROGRAMS += tests/eina_cxx/eina_cxx_suite
-TESTS += tests/eina_cxx/eina_cxx_suite
+### Tests for Eina and Eo
+check_PROGRAMS += tests/eina_cxx/eina_cxx_suite tests/eo_cxx/eo_cxx_suite
+TESTS += tests/eina_cxx/eina_cxx_suite tests/eo_cxx/eo_cxx_suite
 
 tests_eina_cxx_eina_cxx_suite_SOURCES = \
 tests/eina_cxx/eina_cxx_suite.cc \
@@ -232,11 +235,34 @@ tests_eina_cxx_eina_cxx_suite_CPPFLAGS = 
-I$(top_builddir)/src/lib/efl \
 @CHECK_CFLAGS@ \
 @EO_CFLAGS@ \
 @ECORE_CFLAGS@ \
+@ECORE_CXX_CFLAGS@ \
 @EO_CXX_CFLAGS@ \
 @EINA_CXX_CFLAGS@
 tests_eina_cxx_eina_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ 
@USE_EO_LIBS@
 tests_eina_cxx_eina_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 
@USE_EO_INTERNAL_LIBS@
 
+tests_eo_cxx_eo_cxx_suite_SOURCES = \
+tests/eo_cxx/eo_cxx_suite.cc \
+tests/eo_cxx/eo_cxx_test_promise.cc
+
+tests_eo_cxx_eo_cxx_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+-DTESTS_WD=\"`pwd`\" \
+-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eo_cxx\" \
+-DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)/src/tests/eo_cxx\" \
+-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eo_cxx\" \
+-I$(top_builddir)/src/lib/efl \
+-I$(top_builddir)/src/lib/efl/interfaces \
+-I$(top_srcdir)/src/bin/eina_cxx \
+-I$(top_builddir)/src/tests/eina_cxx \
+@CHECK_CFLAGS@ \
+@EO_CFLAGS@ \
+@ECORE_CFLAGS@ \
+@ECORE_CXX_CFLAGS@ \
+@EO_CXX_CFLAGS@ \
+@EINA_CXX_CFLAGS@
+tests_eo_cxx_eo_cxx_suite_LDADD = @CHECK_LIBS@ @USE_EINA_LIBS@ @USE_EO_LIBS@ 
@USE_ECORE_LIBS@
+tests_eo_cxx_eo_cxx_suite_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ 
@USE_EO_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@
+
 ### Tests for ecore
 
 check_PROGRAMS += tests/ecore_cxx/ecore_cxx_suite 
tests/ecore_cxx/cxx_compile_test
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 4a1d6a6..606ae66 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -6,7 +6,7 @@ ecore_eolian_files_legacy = \
        lib/ecore/ecore_exe.eo \
        lib/ecore/efl_loop_timer.eo
 
-ecore_eolian_files = \
+ecore_eolian_files_public = \
        lib/ecore/efl_loop.eo \
        lib/ecore/efl_loop_user.eo \
        lib/ecore/efl_loop_fd.eo \
@@ -20,8 +20,11 @@ ecore_eolian_files = \
        lib/ecore/efl_io_stderr.eo \
        lib/ecore/efl_io_file.eo \
         lib/ecore/efl_io_copier.eo \
+       lib/ecore/ecore_parent.eo
+
+ecore_eolian_files = \
+       $(ecore_eolian_files_public) \
        lib/ecore/efl_promise.eo \
-       lib/ecore/ecore_parent.eo \
        $(ecore_eolian_files_legacy)
 
 ecore_eolian_type_files = \
@@ -300,7 +303,7 @@ endif
 
 if HAVE_JS
 
-generated_ecore_js_bindings = $(ecore_eolian_files:%.eo=%.eo.js.cc)
+generated_ecore_js_bindings = $(ecore_eolian_files_public:%.eo=%.eo.js.cc)
 
 GENERATED_JS_BINDINGS += $(generated_ecore_js_bindings)
 
@@ -308,7 +311,7 @@ endif
 
 if HAVE_CXX11
 
-ecore_eolian_cxx_hh = $(ecore_eolian_files:%.eo=%.eo.hh)
-ecore_eolian_cxx_impl = $(ecore_eolian_files:%.eo=%.eo.impl.hh)
+ecore_eolian_cxx_hh = $(ecore_eolian_files_public:%.eo=%.eo.hh)
+ecore_eolian_cxx_impl = $(ecore_eolian_files_public:%.eo=%.eo.impl.hh)
 
 endif
diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am
index b8fad1c..c142a4b 100644
--- a/src/Makefile_Eolian_Cxx.am
+++ b/src/Makefile_Eolian_Cxx.am
@@ -57,7 +57,7 @@ bin_eolian_cxx_eolian_cxx_SOURCES = \
 
 bin_eolian_cxx_eolian_cxx_CXXFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/eolian_cxx/ \
-@CHECK_CFLAGS@ @EINA_CFLAGS@ @EINA_CXX_CFLAGS@ @EO_CFLAGS@ \
+@CHECK_CFLAGS@ @EINA_CFLAGS@ @EINA_CXX_CFLAGS@ @EO_CXX_CFLAGS@ 
@ECORE_CXX_CFLAGS@ @EO_CFLAGS@ \
 -I$(top_srcdir)/src/bindings/cxx/eina_cxx \
 @EOLIAN_CXX_CFLAGS@ @EOLIAN_CFLAGS@
 
@@ -159,7 +159,7 @@ tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \
 -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eolian_cxx\" \
 @CHECK_CFLAGS@ @EOLIAN_CXX_CFLAGS@ @EINA_CXX_CFLAGS@ \
 @EOLIAN_CFLAGS@ @EINA_CFLAGS@ @EO_CFLAGS@ @ECORE_CFLAGS@ \
-@EO_CXX_CFLAGS@
+@EO_CXX_CFLAGS@ @ECORE_CXX_CFLAGS@
 
 tests_eolian_cxx_eolian_cxx_suite_CFLAGS = 
${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
 tests_eolian_cxx_eolian_cxx_suite_CPPFLAGS = 
${tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS}
diff --git a/src/bindings/cxx/ecore_cxx/Ecore.hh 
b/src/bindings/cxx/ecore_cxx/Ecore.hh
index 75ebc3e..bd2cd7e 100644
--- a/src/bindings/cxx/ecore_cxx/Ecore.hh
+++ b/src/bindings/cxx/ecore_cxx/Ecore.hh
@@ -13,168 +13,6 @@
 #ifdef EFL_BETA_API_SUPPORT
 #include <Ecore.eo.hh>
 #endif
-
-namespace efl { namespace ecore {
-
-template <typename T>
-struct _identity
-{
-  typedef T type;
-};
-
-template <typename F>
-void _ecore_main_loop_thread_safe_call_async_callback(void* data)
-{
-  std::unique_ptr<F> f (static_cast<F*>(data));
-  try
-    {
-      (*f)();
-    }
-  catch(std::bad_alloc const& e)
-    {
-      eina_error_set(ENOMEM);
-    }
-  catch(std::system_error const& e)
-    {
-      efl::eina::set_error_code(e.code());
-    }
-  catch(...)
-    {
-      eina_error_set( efl::eina::unknown_error() );
-    }
-}
-
-template <typename T>
-struct _return_buffer
-{
-  typename std::aligned_storage<sizeof(T),std::alignment_of<T>::value>::type 
buffer;
-};
-
-template <>
-struct _return_buffer<void>
-{
-};
-
-template <typename F>
-struct _data
-{
-  F& f;
-  std::exception_ptr exception;
-  typedef typename std::result_of<F()>::type result_type;
-  _return_buffer<result_type> return_buffer;
-};
-
-template <typename F>
-void* _ecore_main_loop_thread_safe_call_sync_callback_aux(_data<F>* d, 
_identity<void>)
-{
-  d->f();
-  if(eina_error_get())
-    d->exception = 
make_exception_ptr(std::system_error(efl::eina::get_error_code()));
-  return 0;
-}
-
-template <typename F, typename R>
-void* _ecore_main_loop_thread_safe_call_sync_callback_aux(_data<F>* d, 
_identity<R>)
-{
-  typedef R result_type;
-  new (&d->return_buffer.buffer) result_type ( std::move(d->f()) );
-  if(eina_error_get())
-    {
-      d->exception = 
make_exception_ptr(std::system_error(efl::eina::get_error_code()));
-      eina_error_set(0);
-      result_type* p = 
static_cast<result_type*>(static_cast<void*>(&d->return_buffer.buffer));
-      p->~result_type();
-    }
-  return 0;
-}
-
-template <typename F>
-void* _ecore_main_loop_thread_safe_call_sync_callback(void* data)
-{
-  _data<F>* d = static_cast<_data<F>*>(data);
-  try
-    {
-      return _ecore_main_loop_thread_safe_call_sync_callback_aux
-        (d, _identity<typename std::result_of<F()>::type>());
-    }
-  catch(std::bad_alloc const& e)
-    {
-      d->exception = std::current_exception();
-    }
-  catch(std::system_error const& e)
-    {
-      d->exception = std::current_exception();
-    }
-  catch(...)
-    {
-      d->exception = std::current_exception();
-    }
-  return 0;
-}
-
-template <typename F>
-void main_loop_thread_safe_call_async(F&& f)
-{
-  ::ecore_main_loop_thread_safe_call_async( 
&ecore::_ecore_main_loop_thread_safe_call_async_callback<F>
-                                            , new F(std::forward<F>(f)) );
-}
-
-template <typename F>
-void _get_return_value(_data<F>& data, _identity<void>)
-{
-  if(data.exception)
-    {
-      std::rethrow_exception(data.exception);
-    }
-}
-
-template <typename F, typename R>
-R _get_return_value(_data<F>& data, _identity<R>)
-{
-  if(!data.exception)
-    {
-      R* b_ = static_cast<R*>(static_cast<void*>(&data.return_buffer.buffer));
-      struct destroy
-      {
-        destroy(R* x_) : p_(x_)
-        {}
-        ~destroy()
-        {
-          p_->~R();
-        }
-        R* p_;
-      } destroy_temp(b_);
-      return std::move(*b_);
-    }
-  else
-    {
-      std::rethrow_exception(data.exception);
-    }
-}
-
-template <typename F>
-typename std::result_of<F()>::type
-main_loop_thread_safe_call_sync(F&& f)
-{
-  typedef typename std::result_of<F()>::type result_type;
-  _data<F> data {f, nullptr, {}};
-  ::ecore_main_loop_thread_safe_call_sync
-      (&ecore::_ecore_main_loop_thread_safe_call_sync_callback<F>, &data);
-  return _get_return_value(data, _identity<result_type>());
-}
-
-struct ecore_init
-{
-  ecore_init()
-  {
-    ::ecore_init();
-  }
-  ~ecore_init()
-  {
-    ::ecore_shutdown();
-  }
-};
-
-} }
+#include <Ecore_Manual.hh>
 
 #endif
diff --git a/src/bindings/cxx/ecore_cxx/Ecore.hh 
b/src/bindings/cxx/ecore_cxx/Ecore_Manual.hh
similarity index 95%
copy from src/bindings/cxx/ecore_cxx/Ecore.hh
copy to src/bindings/cxx/ecore_cxx/Ecore_Manual.hh
index 75ebc3e..4bc9062 100644
--- a/src/bindings/cxx/ecore_cxx/Ecore.hh
+++ b/src/bindings/cxx/ecore_cxx/Ecore_Manual.hh
@@ -1,5 +1,5 @@
-#ifndef _EFL_ECORE_CXX_ECORE_HH
-#define _EFL_ECORE_CXX_ECORE_HH
+#ifndef _EFL_ECORE_CXX_ECORE_MANUAL_HH
+#define _EFL_ECORE_CXX_ECORE_MANUAL_HH
 
 #include <Ecore.h>
 
@@ -10,10 +10,6 @@
 #include <memory>
 #include <cstring>
 
-#ifdef EFL_BETA_API_SUPPORT
-#include <Ecore.eo.hh>
-#endif
-
 namespace efl { namespace ecore {
 
 template <typename T>
@@ -32,7 +28,7 @@ void _ecore_main_loop_thread_safe_call_async_callback(void* 
data)
     }
   catch(std::bad_alloc const& e)
     {
-      eina_error_set(ENOMEM);
+      eina_error_set( ::EINA_ERROR_OUT_OF_MEMORY);
     }
   catch(std::system_error const& e)
     {
diff --git a/src/bindings/cxx/eina_cxx/Eina.hh 
b/src/bindings/cxx/eina_cxx/Eina.hh
index c986815..f613415 100644
--- a/src/bindings/cxx/eina_cxx/Eina.hh
+++ b/src/bindings/cxx/eina_cxx/Eina.hh
@@ -26,6 +26,7 @@
 #include <eina_workarounds.hh>
 #include <eina_future.hh>
 #include <eina_deleter.hh>
+#include <eina_copy_traits.hh>
 
 /**
  * @page eina_cxx_main Eina C++ (BETA)
diff --git a/src/bindings/cxx/eina_cxx/eina_copy_traits.hh 
b/src/bindings/cxx/eina_cxx/eina_copy_traits.hh
new file mode 100644
index 0000000..0db8bd8
--- /dev/null
+++ b/src/bindings/cxx/eina_cxx/eina_copy_traits.hh
@@ -0,0 +1,43 @@
+///
+/// @file eo_concrete.hh
+///
+
+#ifndef EFL_CXX_EINA_COPY_TRAITS_HH
+#define EFL_CXX_EINA_COPY_TRAITS_HH
+
+namespace efl { namespace eina {
+
+template <typename T, typename Enable = void>
+struct copy_from_c_traits;
+
+template <typename T>
+struct copy_from_c_traits<T, typename 
std::enable_if<std::is_fundamental<T>::value>::type>
+{
+  static void copy_to_unitialized(T* storage, void const* data)
+  {
+    std::memcpy(storage, data, sizeof(T));
+  }
+};
+
+template <typename T, typename Enable = void>
+struct alloc_to_c_traits;
+
+template <typename T>
+struct alloc_to_c_traits<T, typename 
std::enable_if<std::is_fundamental<T>::value>::type>
+{
+  typedef T c_type;
+  static c_type* copy_alloc(T const& value)
+  {
+    c_type* v = static_cast<c_type*>(malloc(sizeof(c_type)));
+    std::memcpy(v, &value, sizeof(c_type));
+    return v;
+  }
+  static void free_alloc(void* data)
+  {
+    ::free(data);
+  }
+};
+    
+} }
+
+#endif
diff --git a/src/bindings/cxx/eo_cxx/Eo.hh b/src/bindings/cxx/eo_cxx/Eo.hh
index b7d1e85..771ee12 100644
--- a/src/bindings/cxx/eo_cxx/Eo.hh
+++ b/src/bindings/cxx/eo_cxx/Eo.hh
@@ -4,8 +4,9 @@
 #include <eo_concrete.hh>
 #include <eo_init.hh>
 #include <eo_wref.hh>
-// #include <eo_inherit.hh>
+//#include <eo_inherit.hh>
 //#include <eo_own_ptr.hh>
+#include <eo_promise.hh>
 #include <eo_cxx_interop.hh>
 #include <eo_event.hh>
 
diff --git a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh 
b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
index 597ef3b..fc1793f 100644
--- a/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
+++ b/src/bindings/cxx/eo_cxx/eo_cxx_interop.hh
@@ -55,14 +55,14 @@ struct out_traits<eina::optional<T&>> { typedef 
eina::optional<T&> type; };
 template <>
 struct out_traits<void*> { typedef void*& type; };
 template <typename T>
-struct out_traits<efl::eina::future<T>> { typedef efl::eina::future<T>& type; 
};
+struct out_traits<efl::shared_future<T>> { typedef efl::shared_future<T>& 
type; };
 
 template <typename T>
 struct inout_traits { typedef T& type; };
 template <>
 struct inout_traits<void> { typedef void* type; };
 template <typename T>
-struct inout_traits<efl::eina::future<T>> { typedef efl::eina::future<T>& 
type; };
+struct inout_traits<efl::shared_future<T>> { typedef efl::shared_future<T>& 
type; };
 
 template <typename T>
 struct return_traits { typedef T type; };
@@ -126,7 +126,11 @@ void assign_out_impl(T& lhs, Eo const* rhs, tag<T&, Eo 
const*>
   lhs._reset(const_cast<Eo*>(rhs));
 }
 template <typename T>
-void assign_out_impl(efl::eina::future<T>& /*v*/, Eina_Promise*, 
tag<efl::eina::future<T>&, Eina_Promise*>)
+void assign_out_impl(efl::promise<T>& /*v*/, Eina_Promise*, 
tag<efl::promise<T>&, Eina_Promise*>)
+{
+}
+template <typename T>
+void assign_out_impl(efl::shared_future<T>& /*v*/, Efl_Future*, 
tag<efl::shared_future<T>&, Efl_Future*>)
 {
 }
 template <typename Tag>
@@ -257,7 +261,12 @@ Eo const* convert_inout_impl(T v, tag<T, Eo const*>
   return v._eo_ptr();
 }
 template <typename T>
-Eina_Promise* convert_inout_impl(efl::eina::future<T>& /*v*/, 
tag<efl::eina::future<T>, Eina_Promise*>)
+Eina_Promise* convert_inout_impl(efl::promise<T>& /*v*/, tag<efl::promise<T>, 
Eina_Promise*>)
+{
+  return nullptr;
+}
+template <typename T>
+Efl_Future* convert_inout_impl(efl::shared_future<T>& /*v*/, 
tag<efl::shared_future<T>, Efl_Future*>)
 {
   return nullptr;
 }
@@ -511,7 +520,12 @@ inline const char* 
convert_to_c_impl(efl::eina::stringshare x, tag<const char*,
    return eina_stringshare_ref(x.c_str());
 }
 template <typename T>
-Eina_Promise* convert_to_c_impl(efl::eina::future<T> const&, 
tag<Eina_Promise*, efl::eina::future<T>const&>)
+Eina_Promise* convert_to_c_impl(efl::promise<T> const&, tag<Eina_Promise*, 
efl::promise<T>const&>)
+{
+  std::abort();
+}
+template <typename T>
+Efl_Future* convert_to_c_impl(efl::shared_future<T> const&, tag<Efl_Future*, 
efl::shared_future<T>const&>)
 {
   std::abort();
 }
@@ -653,11 +667,13 @@ eina::accessor<T> convert_to_return(Eina_Accessor* value, 
tag<Eina_Accessor*, ei
   return eina::accessor<T>{ value };
 }
 template <typename T>
-struct is_future : std::false_type {};
-template <typename T>
-struct is_future<efl::eina::future<T>> : std::true_type {};
+efl::promise<T> convert_to_return(Eina_Promise* /*value*/, tag<Eina_Promise*, 
efl::promise<T>>)
+{
+  std::abort();
+  return {};
+}
 template <typename T>
-T convert_to_return(Eina_Promise* /*value*/, tag<Eina_Promise*, T>, typename 
std::enable_if<is_future<T>::value>::type* = 0)
+efl::shared_future<T> convert_to_return(Efl_Future* /*value*/, 
tag<Efl_Future*, efl::shared_future<T>>)
 {
   std::abort();
   return {};
diff --git a/src/bindings/cxx/eo_cxx/eo_promise.hh 
b/src/bindings/cxx/eo_cxx/eo_promise.hh
new file mode 100644
index 0000000..b325d9c
--- /dev/null
+++ b/src/bindings/cxx/eo_cxx/eo_promise.hh
@@ -0,0 +1,416 @@
+///
+/// @file eo_concrete.hh
+///
+
+#ifndef EFL_CXX_EO_PROMISE_HH
+#define EFL_CXX_EO_PROMISE_HH
+
+#include <Efl.h>
+
+#include <Eina.hh>
+#include <Ecore_Manual.hh>
+
+#include <mutex>
+#include <condition_variable>
+
+namespace efl {
+
+namespace _impl {
+
+template <typename F, typename...Args>
+struct future_invoke_result_of;
+
+template <typename F, typename A0>
+struct future_invoke_result_of<F, A0>
+{
+   typedef typename std::result_of<F(A0)>::type type;
+};
+
+template <typename F>
+struct future_invoke_result_of<F, void>
+{
+   typedef typename std::result_of<F()>::type type;
+};
+  
+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;
+        eina::copy_from_c_traits<A0>::copy_to_unitialized
+          (static_cast<A0*>(static_cast<void*>(&storage)), info->value);
+        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 <typename A0, typename A1, typename...OtherArgs, typename F>
+// typename future_invoke_result_of<F, A0, A1, OtherArgs...>::type
+void
+future_invoke(F f, Efl_Event const* event)
+{
+   Efl_Future_Event_Success* info = 
static_cast<Efl_Future_Event_Success*>(event->info);
+   
+}
+  
+}
+  
+template <typename T>
+struct progress;
+
+namespace _impl {
+
+template <typename V = char>
+struct wait_state
+{
+   bool available = false;
+   bool has_failed = false;
+   std::mutex mutex;
+   std::condition_variable cv;
+   typename std::aligned_storage<sizeof(V), alignof(V)>::type storage;
+   Eina_Error error;
+};
+
+static void get_error_cb(void* data, Efl_Event const* event)
+{ 
+   struct wait_state<>* wait_state = static_cast<struct wait_state<>*>(data);
+   Efl_Future_Event_Failure* info = 
static_cast<Efl_Future_Event_Failure*>(event->info);
+   std::unique_lock<std::mutex> l(wait_state->mutex);
+   wait_state->error = info->error;
+   wait_state->has_failed = true;
+   wait_state->available = true;
+   wait_state->cv.notify_one();
+}
+  
+struct shared_future_common
+{
+   explicit shared_future_common(Efl_Future* future)
+     : _future(future) {}
+   shared_future_common()
+     : _future(nullptr) {}
+   ~shared_future_common()
+   {
+      if(_future)
+        efl_unref(_future);
+   }
+   shared_future_common(shared_future_common const& future)
+     : _future(efl_ref(future._future))
+   {
+   }
+   shared_future_common& operator=(shared_future_common const& other)
+   {
+      _self_type tmp(other);
+      tmp.swap(*this);
+      return *this;
+   }
+   shared_future_common(shared_future_common&& future)
+     : _future(future._future)
+   {
+      future._future = nullptr;
+   }
+   shared_future_common& operator=(shared_future_common&& other)
+   {
+      other.swap(*this);
+      return *this;
+   }
+   void swap(shared_future_common& other)
+   {
+      std::swap(_future, other._future);
+   }
+   bool valid() const noexcept
+   {
+      return _future != nullptr;
+   }
+   void wait() const
+   {
+      if(eina_main_loop_is())
+        throw std::runtime_error("Deadlock");
+
+      struct wait_state<> wait_state;
+      
+      efl::ecore::main_loop_thread_safe_call_async
+        ([&]
+         {
+            efl_future_then(this->_future, &wait_success, &wait_success, 
nullptr, &wait_state);
+         });
+
+      std::unique_lock<std::mutex> lock(wait_state.mutex);
+      while(!wait_state.available)
+        wait_state.cv.wait(lock);
+   }
+   static void wait_success(void* data, Efl_Event const*)
+   {
+      struct wait_state<>* wait_state = static_cast<struct 
wait_state<>*>(data);
+      std::unique_lock<std::mutex> l(wait_state->mutex);
+      wait_state->available = true;
+      wait_state->cv.notify_one();
+   }
+
+   typedef Efl_Future* native_handle_type;
+   typedef Efl_Future const* const_native_handle_type;
+   native_handle_type native_handle() noexcept { return _future; }
+   const_native_handle_type native_handle() const noexcept { return _future; }
+
+   typedef shared_future_common _self_type;
+   Efl_Future* _future;
+};
+  
+template <typename T>
+struct shared_future_1_type : private 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;
+
+   T get() const
+   {
+      if(eina_main_loop_is())
+        throw std::runtime_error("Deadlock");
+
+      struct wait_state<T> wait_state;
+
+      efl::ecore::main_loop_thread_safe_call_async
+        ([&]
+         {
+            efl_future_then(this->_future, &get_success, &_impl::get_error_cb, 
nullptr, &wait_state);
+         });
+
+      {
+        std::unique_lock<std::mutex> lock(wait_state.mutex);
+        while(!wait_state.available)
+          wait_state.cv.wait(lock);
+      }
+      if(wait_state.has_failed)
+        EFL_CXX_THROW(eina::system_error(eina::error_code(wait_state.error, 
eina::eina_error_category()), "EFL Eina Error"));
+      return *static_cast<T*>(static_cast<void*>(&wait_state.storage));
+   }
+
+   static void get_success(void* data, Efl_Event const* event)
+   {
+      struct wait_state<T>* wait_state = static_cast<struct 
wait_state<T>*>(data);
+      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);
+      wait_state->available = true;
+      wait_state->cv.notify_one();
+   }
+
+   typedef shared_future_1_type<T> _self_type;
+};
+
+template <typename...Args>
+struct shared_future_varargs_type : private 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;
+
+   typedef std::tuple<Args...> tuple_type;
+
+   std::tuple<Args...> get() const
+   {
+      if(eina_main_loop_is())
+        throw std::runtime_error("Deadlock");
+
+      struct wait_state<tuple_type> wait_state;
+
+      efl::ecore::main_loop_thread_safe_call_async
+        ([&]
+         {
+            efl_future_then(this->_future, &get_success, &_impl::get_error_cb, 
nullptr, &wait_state);
+         });
+
+      {
+        std::unique_lock<std::mutex> lock(wait_state.mutex);
+        while(!wait_state.available)
+          wait_state.cv.wait(lock);
+      }
+      if(wait_state.has_failed)
+        EFL_CXX_THROW(eina::system_error(eina::error_code(wait_state.error, 
eina::eina_error_category()), "EFL Eina Error"));
+      return 
*static_cast<tuple_type*>(static_cast<void*>(&wait_state.storage));
+   }
+
+   template <std::size_t N>
+   static void read_accessor(Eina_Accessor* accessor
+                             , std::tuple<typename 
std::aligned_storage<sizeof(Args), alignof(Args)>::type...>& storage_tuple
+                             , wait_state<tuple_type>* wait_state
+                             , std::false_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);
+
+          std::cout << "copied value " << 
*static_cast<type*>(static_cast<void*>(&std::get<N>(storage_tuple)))
+                    << std::endl;
+     
+          _self_type::read_accessor<N+1>(accessor, storage_tuple, wait_state
+                                         , std::integral_constant<bool, (N+1 
== sizeof...(Args))>());
+        }
+      else
+        {
+          std::abort();
+          // some error
+        }
+   }
+
+   template <std::size_t N, std::size_t...I>
+   static void read_accessor_end(std::tuple<typename 
std::aligned_storage<sizeof(Args), alignof(Args)>::type...>& storage_tuple
+                                 , wait_state<tuple_type>* wait_state
+                                 , eina::index_sequence<I...>)
+   {
+      std::unique_lock<std::mutex> l(wait_state->mutex);
+
+      new (&wait_state->storage) tuple_type{(*static_cast<typename 
std::tuple_element<I, tuple_type>::type*>
+                                             
(static_cast<void*>(&std::get<I>(storage_tuple))))...};
+
+      wait_state->available = true;
+      wait_state->cv.notify_one();
+   }
+  
+   template <std::size_t N>
+   static void read_accessor(Eina_Accessor*
+                             , std::tuple<typename 
std::aligned_storage<sizeof(Args), alignof(Args)>::type...>& storage_tuple
+                             , wait_state<tuple_type>* wait_state
+                             , std::true_type)
+   {
+      _self_type::read_accessor_end<N>(storage_tuple, wait_state, 
eina::make_index_sequence<sizeof...(Args)>{});
+   }
+  
+   static void get_success(void* data, Efl_Event const* event)
+   {
+      struct wait_state<tuple_type>* wait_state = static_cast<struct 
wait_state<tuple_type>*>(data);
+      Efl_Future_Event_Success* info = 
static_cast<Efl_Future_Event_Success*>(event->info);
+
+      Eina_Accessor* accessor = static_cast<Eina_Accessor*>(info->value);
+      std::tuple<typename std::aligned_storage<sizeof(Args), 
alignof(Args)>::type...> storage_tuple;
+
+      _self_type::read_accessor<0u>(accessor, storage_tuple, wait_state, 
std::false_type());
+   }
+  
+   typedef shared_future_varargs_type<Args...> _self_type;
+};
+  
+}
+
+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
+{
+   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;
+
+   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;
+};
+
+template <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(shared_future<Args...> future, Success success_cb, Error error_cb)
+{
+  struct private_data
+  {
+    Success success_cb;
+    Error error_cb;
+    shared_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);
+           // 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...Args>
+struct promise
+{
+  
+};
+    
+}
+
+#endif
diff --git a/src/lib/eolian_cxx/grammar/type_impl.hpp 
b/src/lib/eolian_cxx/grammar/type_impl.hpp
index 6e18b2b..ac1118f 100644
--- a/src/lib/eolian_cxx/grammar/type_impl.hpp
+++ b/src/lib/eolian_cxx/grammar/type_impl.hpp
@@ -256,7 +256,13 @@ struct visitor_generate
         , {"promise", nullptr, nullptr, [&]
            {
              return replace_outer
-             (complex, regular_type_def{" ::efl::eina::future", 
complex.outer.base_qualifier, {}});
+             (complex, regular_type_def{" ::efl::promise", 
complex.outer.base_qualifier, {}});
+           }           
+          }
+        , {"future", nullptr, nullptr, [&]
+           {
+             return replace_outer
+             (complex, regular_type_def{" ::efl::shared_future", 
complex.outer.base_qualifier, {}});
            }           
           }
         , {"iterator", nullptr, nullptr, [&]
diff --git a/src/tests/eo_cxx/eo_cxx_suite.cc b/src/tests/eo_cxx/eo_cxx_suite.cc
new file mode 100644
index 0000000..2362d38
--- /dev/null
+++ b/src/tests/eo_cxx/eo_cxx_suite.cc
@@ -0,0 +1,27 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "eo_cxx_suite.h"
+#include "../efl_check.h"
+
+static const Efl_Test_Case etc[] = {
+   { "Promise", eo_cxx_test_promise },
+   { NULL, NULL }
+};
+
+int
+main(int argc, char* argv[])
+{
+   int failed_count;
+
+   if (!_efl_test_option_disp(argc, argv, etc))
+     return 0;
+
+   putenv(const_cast<char*>("EFL_RUN_IN_TREE=1"));
+
+   failed_count = _efl_suite_build_and_run(argc - 1, (const char **)argv + 1,
+                                           "Eo C++", etc);
+
+   return (failed_count == 0) ? 0 : 255;
+}
diff --git a/src/tests/eo_cxx/eo_cxx_suite.h b/src/tests/eo_cxx/eo_cxx_suite.h
new file mode 100644
index 0000000..a5a1d61
--- /dev/null
+++ b/src/tests/eo_cxx/eo_cxx_suite.h
@@ -0,0 +1,11 @@
+#ifndef _EINA_CXX_SUITE_H
+#define _EINA_CXX_SUITE_H
+
+#include <cassert>
+#include <algorithm>
+
+#include <check.h>
+
+void eo_cxx_test_promise(TCase* tc);
+
+#endif /* _EINA_CXX_SUITE_H */
diff --git a/src/tests/eo_cxx/eo_cxx_test_promise.cc 
b/src/tests/eo_cxx/eo_cxx_test_promise.cc
new file mode 100644
index 0000000..b3a2b32
--- /dev/null
+++ b/src/tests/eo_cxx/eo_cxx_test_promise.cc
@@ -0,0 +1,347 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <Eina.hh>
+#include <Eo.hh>
+#include <Ecore.hh>
+
+#include "eo_cxx_suite.h"
+
+START_TEST(eo_cxx_future_construct_and_destroy)
+{
+   Efl_Promise *p;
+   Efl_Future *f;
+
+   ecore_init();
+
+   {
+      p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p);
+  
+      f = efl_promise_future_get(p);
+      fail_if(!f);
+
+      efl::shared_future<int> future(efl_ref(f));
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_wait)
+{
+   Efl_Promise *p;
+   Efl_Future *f;
+
+   ecore_init();
+
+   p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+   fail_if(!p);
+  
+   f = efl_promise_future_get(p);
+   fail_if(!f);
+
+   {
+      efl::shared_future<int> future(efl_ref(f));
+
+      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
+                              ([&]
+                               {
+                                  int* i = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i = 5;
+                                  efl_promise_value_set(p, i, & ::free);
+                               });
+                         
+                            future.wait();
+                            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+                         });
+
+      ecore_main_loop_begin();
+   
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_get)
+{
+   Efl_Promise *p;
+   Efl_Future *f;
+
+   ecore_init();
+
+   p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+   fail_if(!p);
+  
+   f = efl_promise_future_get(p);
+   fail_if(!f);
+
+   {
+      efl::shared_future<int> future(efl_ref(f));
+
+      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
+                              ([&]
+                               {
+                                  int* i = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i = 5;
+                                  efl_promise_value_set(p, i, & ::free);
+                               });
+                         
+                            int i = future.get();
+                            ck_assert_int_eq(i, 5);
+                            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+                         });
+
+      ecore_main_loop_begin();
+   
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_get_error)
+{
+   Efl_Promise *p;
+   Efl_Future *f;
+
+   ecore_init();
+
+   p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+   fail_if(!p);
+  
+   f = efl_promise_future_get(p);
+   fail_if(!f);
+
+   {
+      efl::shared_future<int> future(efl_ref(f));
+
+      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
+                              ([&]
+                               {
+                                  efl_promise_failed_set(p, 
EINA_ERROR_OUT_OF_MEMORY);
+                               });
+
+                            try {
+                               future.get();
+                               ck_abort_msg("Execution should not have 
continued, exception expected");
+                            }
+                            catch(std::system_error const& e)
+                              {
+                              }
+                            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+                         });
+
+      ecore_main_loop_begin();
+   
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_then_value)
+{
+   Efl_Promise *promise;
+   Efl_Future *f;
+
+   ecore_init();
+
+   promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+   fail_if(!promise);
+  
+   f = efl_promise_future_get(promise);
+   fail_if(!f);
+
+   {
+      efl::shared_future<int> future(efl_ref(f)), rfuture;
+
+      
+      std::thread thread
+        ([&]
+         {
+            efl::ecore::main_loop_thread_safe_call_sync
+              ([&]
+               {
+                  rfuture = then
+                    (future, [] (int i) -> int
+                     {
+                        ck_assert_int_eq(i, 5);
+                        return 42;
+                     }, [] (std::error_code)
+                     {
+                        throw std::bad_alloc();
+                     });
+               });
+            efl::ecore::main_loop_thread_safe_call_async
+              ([&]
+               {
+                  int* i = static_cast<int*>(malloc(sizeof(int)));
+                  *i = 5;
+                  efl_promise_value_set(promise, i, &::free);
+               });
+
+            int i = rfuture.get();
+            ck_assert_int_eq(i, 42);
+            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+         });
+
+      ecore_main_loop_begin();
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_composite_construct_and_destroy)
+{
+   ecore_init();
+
+   {
+      Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p1);
+  
+      Efl_Future *f1 = efl_promise_future_get(p1);
+      fail_if(!f1);
+
+      Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p1);
+  
+      Efl_Future *f2 = efl_promise_future_get(p2);
+      fail_if(!f2);
+
+      Efl_Future *f3 = efl_future_all(f1, f2);
+      fail_if(!f3);
+      
+      efl::shared_future<int> future1(efl_ref(f1))
+        , future2(efl_ref(f2));
+      efl::shared_future<int, int> future3(efl_ref(f3));
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_composite_wait)
+{
+   ecore_init();
+
+   {
+      Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p1);
+  
+      Efl_Future* f1 = efl_promise_future_get(p1);
+      fail_if(!f1);
+
+      Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p2);
+  
+      Efl_Future* f2 = efl_promise_future_get(p2);
+      fail_if(!f2);
+
+      Efl_Future *f3 = efl_future_all(f1, f2);
+      fail_if(!f3);
+      
+      efl::shared_future<int> future1(efl_ref(f1))
+        , future2(efl_ref(f2));
+      efl::shared_future<int, int> future3(efl_ref(f3));
+
+      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
+                              ([&]
+                               {
+                                  int* i1 = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i1 = 5;
+                                  efl_promise_value_set(p1, i1, & ::free);
+                                  int* i2 = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i2 = 42;
+                                  efl_promise_value_set(p2, i2, & ::free);
+                               });
+
+                            future3.wait();
+                            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+                         });
+
+      ecore_main_loop_begin();
+   
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+START_TEST(eo_cxx_future_composite_get)
+{
+   ecore_init();
+
+   {
+      Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p1);
+  
+      Efl_Future *f1 = efl_promise_future_get(p1);
+      fail_if(!f1);
+
+      Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get());
+      fail_if(!p2);
+  
+      Efl_Future *f2 = efl_promise_future_get(p2);
+      fail_if(!f2);
+      
+      Efl_Future *f3 = efl_future_all(f1, f2);
+      fail_if(!f3);
+      
+      efl::shared_future<int> future1(efl_ref(f1))
+        , future2(efl_ref(f2));
+      efl::shared_future<int, int> future3(efl_ref(f3));
+
+      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
+                              ([&]
+                               {
+                                  int* i1 = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i1 = 5;
+                                  efl_promise_value_set(p1, i1, & ::free);
+                                  int* i2 = 
static_cast<int*>(malloc(sizeof(int)));
+                                  *i2 = 42;
+                                  efl_promise_value_set(p2, i2, & ::free);
+                               });
+                         
+                            std::tuple<int, int> tuple = future3.get();
+                            ck_assert_int_eq(std::get<0>(tuple), 5);
+                            ck_assert_int_eq(std::get<1>(tuple), 42);
+                            efl::ecore::main_loop_thread_safe_call_sync([] { 
ecore_main_loop_quit(); });
+                         });
+
+      ecore_main_loop_begin();
+   
+      thread.join();
+   }
+   ecore_shutdown();
+}
+END_TEST
+
+void
+eo_cxx_test_promise(TCase* tc)
+{
+  tcase_add_test(tc, eo_cxx_future_construct_and_destroy);
+  tcase_add_test(tc, eo_cxx_future_wait);
+  tcase_add_test(tc, eo_cxx_future_get);
+  tcase_add_test(tc, eo_cxx_future_get_error);
+  tcase_add_test(tc, eo_cxx_future_then_value);
+  tcase_add_test(tc, eo_cxx_future_composite_construct_and_destroy);
+  tcase_add_test(tc, eo_cxx_future_composite_wait);
+  tcase_add_test(tc, eo_cxx_future_composite_get);
+}

-- 


Reply via email to