summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-09-20 23:30:13 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-09-20 23:30:29 -0300
commit10293e652055a5e741f3b9f87c14e7919bb2d267 (patch)
tree146291b7417d2054f26a5123edfa470d863e87fa
parentbed6c84afb2694d3a1186c6878b9338503f55021 (diff)
eo-cxx: Add progress to future and promise
-rw-r--r--src/bindings/cxx/eo_cxx/eo_future.hh199
-rw-r--r--src/bindings/cxx/eo_cxx/eo_promise.hh121
-rw-r--r--src/bindings/cxx/eo_cxx/eo_promise_meta.hh44
-rw-r--r--src/tests/eo_cxx/eo_cxx_test_promise.cc40
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 7154b5f89b..fbab9657c2 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
116 Efl_Future* _future; 116 Efl_Future* _future;
117}; 117};
118 118
119template <typename T> 119template <typename T, typename Progress = void>
120struct shared_future_1_type : private shared_future_common 120struct shared_future_1_type : shared_future_common
121{ 121{
122 typedef shared_future_common _base_type; 122 typedef shared_future_common _base_type;
123 123
124 using _base_type::_base_type; 124 using _base_type::_base_type;
125 using _base_type::swap; 125 shared_future_1_type() = default;
126 using _base_type::valid; 126 shared_future_1_type(shared_future_common const& other)
127 using _base_type::native_handle; 127 : _base_type(other) {}
128 using _base_type::wait;
129 typedef _base_type::native_handle_type native_handle_type;
130 128
131 T get() const 129 T get() const
132 { 130 {
@@ -162,20 +160,17 @@ struct shared_future_1_type : private shared_future_common
162 wait_state->cv.notify_one(); 160 wait_state->cv.notify_one();
163 } 161 }
164 162
165 typedef shared_future_1_type<T> _self_type; 163 typedef shared_future_1_type<T, Progress> _self_type;
166}; 164};
167 165
168template <typename T> 166template <typename T>
169struct shared_race_future_1_type : private shared_future_common 167struct shared_race_future_1_type : shared_future_common
170{ 168{
171 typedef shared_future_common _base_type; 169 typedef shared_future_common _base_type;
172 170
173 using _base_type::_base_type; 171 using _base_type::_base_type;
174 using _base_type::swap; 172 shared_race_future_1_type(_base_type const& other)
175 using _base_type::valid; 173 : _base_type(other) {}
176 using _base_type::native_handle;
177 using _base_type::wait;
178 typedef _base_type::native_handle_type native_handle_type;
179 174
180 T get() const 175 T get() const
181 { 176 {
@@ -211,20 +206,18 @@ struct shared_race_future_1_type : private shared_future_common
211 wait_state->cv.notify_one(); 206 wait_state->cv.notify_one();
212 } 207 }
213 208
214 typedef shared_future_1_type<T> _self_type; 209 typedef shared_race_future_1_type<T> _self_type;
215}; 210};
216 211
217template <typename...Args> 212template <typename...Args>
218struct shared_future_varargs_type : private shared_future_common 213struct shared_future_varargs_type : shared_future_common
219{ 214{
220 typedef shared_future_common _base_type; 215 typedef shared_future_common _base_type;
221 216
222 using _base_type::_base_type; 217 using _base_type::_base_type;
223 using _base_type::swap; 218 shared_future_varargs_type() = default;
224 using _base_type::valid; 219 shared_future_varargs_type(_base_type const& other)
225 using _base_type::native_handle; 220 : _base_type(other) {}
226 using _base_type::wait;
227 typedef _base_type::native_handle_type native_handle_type;
228 221
229 typedef std::tuple<Args...> tuple_type; 222 typedef std::tuple<Args...> tuple_type;
230 223
@@ -314,17 +307,59 @@ struct shared_future_varargs_type : private shared_future_common
314} 307}
315 308
316template <typename...Args> 309template <typename...Args>
317struct 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 310struct shared_future : private
311 std::conditional
312 <
313 sizeof...(Args) == 1
314 , _impl::shared_future_1_type<typename std::tuple_element<0u, std::tuple<Args...>>::type>
315 , typename std::conditional
316 <_impl::is_progress<typename std::tuple_element<sizeof...(Args) - 1, std::tuple<Args...>>::type>::value
317 , typename std::conditional
318 <sizeof...(Args) == 2
319 , _impl::shared_future_1_type<Args...>
320 , _impl::shared_future_varargs_type<Args...>
321 >::type
322 , _impl::shared_future_varargs_type<Args...>
323 >::type
324 >::type
318{ 325{
319 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; 326 typedef typename
320 327 std::conditional
328 <
329 sizeof...(Args) == 1
330 , _impl::shared_future_1_type<Args...>
331 , typename std::conditional
332 <_impl::is_progress<typename std::tuple_element<sizeof...(Args) - 1, std::tuple<Args...>>::type>::value
333 , typename std::conditional
334 <sizeof...(Args) == 2
335 , _impl::shared_future_1_type<Args...>
336 , _impl::shared_future_varargs_type<Args...>
337 >::type
338 , _impl::shared_future_varargs_type<Args...>
339 >::type
340 >::type
341 _base_type;
342 typedef typename _impl::progress_param<Args...>::type progress_param_type;
343 typedef typename _impl::progress_type<progress_param_type>::type progress_type;
344 typedef typename _base_type::native_handle_type native_handle_type;
321 using _base_type::_base_type; 345 using _base_type::_base_type;
322 using _base_type::swap; 346 using _base_type::swap;
323 using _base_type::valid; 347 using _base_type::valid;
324 using _base_type::get; 348 using _base_type::get;
325 using _base_type::wait; 349 using _base_type::wait;
326 using _base_type::native_handle; 350 using _base_type::native_handle;
327 typedef typename _base_type::native_handle_type native_handle_type; 351
352 shared_future() = default;
353 template <typename...OtherArgs>
354 shared_future(shared_future<OtherArgs...> const& other
355 , typename std::enable_if<_impl::is_progress_param_compatible
356 <progress_param_type, typename _impl::progress_param<OtherArgs...>::type>::value>::type* = nullptr)
357 : _base_type(static_cast< _impl::shared_future_common const&>(other))
358 {
359 }
360
361 template <typename...OtherArgs>
362 friend struct shared_future;
328}; 363};
329 364
330template <typename...Args> 365template <typename...Args>
@@ -350,7 +385,119 @@ template <typename...Args>
350struct is_race_future<shared_race_future<Args...>> : std::true_type {}; 385struct is_race_future<shared_race_future<Args...>> : std::true_type {};
351 386
352} 387}
388
389template <template <typename...> class Future, typename...Args, typename F>
390typename std::enable_if
391<
392 !std::is_same<typename Future<Args...>::progress_type, void>::value
393>::type on_progress(Future<Args...> future, F function)
394{
395 struct private_data
396 {
397 F progress_cb;
398 Future<Args...> future;
399 };
400 private_data* pdata = new private_data
401 {std::move(function), std::move(future)};
402
403 typedef typename Future<Args...>::progress_type progress_type;
404
405 Efl_Event_Cb raw_progress_cb =
406 [] (void* data, Efl_Event const* event)
407 {
408 private_data* pdata = static_cast<private_data*>(data);
409 try
410 {
411 Efl_Future_Event_Progress const* info = static_cast<Efl_Future_Event_Progress const*>(event->info);
412 pdata->progress_cb(*static_cast<progress_type const*>(info->progress));
413 }
414 catch(...)
415 {
416 // what should happen if progress_cb fails?
417 }
418 };
419 Efl_Event_Cb raw_delete_cb =
420 [] (void* data, Efl_Event const*)
421 {
422 private_data* pdata = static_cast<private_data*>(data);
423 delete pdata;
424 };
425
426 assert(pdata->future.valid());
427 efl_future_then(pdata->future.native_handle(), raw_delete_cb, raw_delete_cb, raw_progress_cb, pdata);
428}
429
430template <template <typename...> class Future, typename...Args, typename Success, typename Error>
431shared_future
432<
433 typename std::enable_if
434 <
435 !std::is_same<void, typename std::tuple_element<0, std::tuple<Args...>>::type>::value
436 && !std::is_same<void, typename std::result_of<Success(Args...)>::type>::value
437 , typename std::result_of<Success(Args...)>::type
438 >::type
439> then(Future<Args...> future, Success success_cb, Error error_cb)
440{
441 struct private_data
442 {
443 Success success_cb;
444 Error error_cb;
445 Future<Args...> future;
446 };
447 private_data* pdata = new private_data
448 {std::move(success_cb), std::move(error_cb), std::move(future)};
449
450 Efl_Event_Cb raw_success_cb =
451 [] (void* data, Efl_Event const* event)
452 {
453 private_data* pdata = static_cast<private_data*>(data);
454 try
455 {
456 _impl::future_invoke<Args...>(pdata->success_cb, event, _impl::is_race_future<Future<Args...>>{});
457 // should value_set the next promise
458 }
459 catch(...)
460 {
461 // should fail the next promise
462 }
463 delete pdata;
464 };
465 Efl_Event_Cb raw_error_cb =
466 [] (void* data, Efl_Event const* event)
467 {
468 private_data* pdata = static_cast<private_data*>(data);
469 Efl_Future_Event_Failure* info = static_cast<Efl_Future_Event_Failure*>(event->info);
470 pdata->error_cb(eina::error_code(info->error, eina::eina_error_category()));
471 // should error the next promise (or should the promise do that for me automatically?)
472 delete pdata;
473 };
474
475 assert(pdata->future.valid());
476 Efl_Future* new_future
477 = efl_future_then(pdata->future.native_handle(), raw_success_cb, raw_error_cb, nullptr, pdata);
478 return shared_future<typename std::result_of<Success(Args...)>::type>{efl_ref(new_future)};
479}
353 480
481template <typename...Args, typename F>
482void then(shared_future<Args...> future, F function)
483{
484
485}
486
487template <typename...Args1, typename...Args2, typename...Futures>
488typename _impl::all_result_type<shared_future<Args1...>, shared_future<Args2...>, Futures...>::type
489all(shared_future<Args1...> future1, shared_future<Args2...> future2, Futures...futures)
490{
491 return _impl::all_impl(future1, future2, futures...);
492}
493
494template <typename...Args1, typename...Args2, typename...Futures>
495typename _impl::race_result_type<shared_future<Args1...>, shared_future<Args2...>, Futures...>::type
496race(shared_future<Args1...> future1, shared_future<Args2...> future2, Futures...futures)
497{
498 return _impl::race_impl(future1, future2, futures...);
499}
500
354} 501}
355 502
356#endif 503#endif
diff --git a/src/bindings/cxx/eo_cxx/eo_promise.hh b/src/bindings/cxx/eo_cxx/eo_promise.hh
index f3b8714329..943507fc55 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 {
22template <typename...Args> 22template <typename...Args>
23struct shared_future; 23struct shared_future;
24 24
25template <typename T>
26struct progress;
27
28template <template <typename...> class Future, typename...Args, typename Success, typename Error>
29shared_future
30<
31 typename std::enable_if
32 <
33 !std::is_same<void, typename std::tuple_element<0, std::tuple<Args...>>::type>::value
34 && !std::is_same<void, typename std::result_of<Success(Args...)>::type>::value
35 , typename std::result_of<Success(Args...)>::type
36 >::type
37> then(Future<Args...> future, Success success_cb, Error error_cb)
38{
39 struct private_data
40 {
41 Success success_cb;
42 Error error_cb;
43 Future<Args...> future;
44 };
45 private_data* pdata = new private_data
46 {std::move(success_cb), std::move(error_cb), std::move(future)};
47
48 Efl_Event_Cb raw_success_cb =
49 [] (void* data, Efl_Event const* event)
50 {
51 private_data* pdata = static_cast<private_data*>(data);
52 try
53 {
54 _impl::future_invoke<Args...>(pdata->success_cb, event, _impl::is_race_future<Future<Args...>>{});
55 // should value_set the next promise
56 }
57 catch(...)
58 {
59 // should fail the next promise
60 }
61 delete pdata;
62 };
63 Efl_Event_Cb raw_error_cb =
64 [] (void* data, Efl_Event const* event)
65 {
66 private_data* pdata = static_cast<private_data*>(data);
67 Efl_Future_Event_Failure* info = static_cast<Efl_Future_Event_Failure*>(event->info);
68 pdata->error_cb(eina::error_code(info->error, eina::eina_error_category()));
69 // should error the next promise (or should the promise do that for me automatically?)
70 delete pdata;
71 };
72
73 assert(pdata->future.valid());
74 Efl_Future* new_future
75 = efl_future_then(pdata->future.native_handle(), raw_success_cb, raw_error_cb, nullptr, pdata);
76 return shared_future<typename std::result_of<Success(Args...)>::type>{efl_ref(new_future)};
77}
78
79template <typename...Args, typename F>
80void then(shared_future<Args...> future, F function)
81{
82
83}
84
85template <typename...Args1, typename...Args2, typename...Futures>
86typename _impl::all_result_type<shared_future<Args1...>, shared_future<Args2...>, Futures...>::type
87all(shared_future<Args1...> future1, shared_future<Args2...> future2, Futures...futures)
88{
89 return _impl::all_impl(future1, future2, futures...);
90}
91
92template <typename...Args1, typename...Args2, typename...Futures>
93typename _impl::race_result_type<shared_future<Args1...>, shared_future<Args2...>, Futures...>::type
94race(shared_future<Args1...> future1, shared_future<Args2...> future2, Futures...futures)
95{
96 return _impl::race_impl(future1, future2, futures...);
97}
98
99namespace _impl { 25namespace _impl {
100 26
101struct promise_common 27struct promise_common
@@ -144,15 +70,28 @@ struct promise_common
144 70
145 Efl_Promise* _promise; 71 Efl_Promise* _promise;
146}; 72};
147 73
148template <typename T> 74template <typename P>
149struct promise_1_type : promise_common 75struct promise_progress : promise_common
150{ 76{
151 typedef promise_common _base_type; 77 void set_progress(P const& progress)
152 using _base_type::_base_type; 78 {
153 using _base_type::swap; 79 efl_promise_progress_set(this->_promise, &progress);
154 using _base_type::set_exception; 80 }
81};
82
83template <>
84struct promise_progress<void> : promise_common
85{
86 void set_progress()
87 {
88 efl_promise_progress_set(this->_promise, nullptr);
89 }
90};
155 91
92template <typename T, typename Progress>
93struct promise_1_type : promise_progress<Progress>
94{
156 void set_value(T const& v) 95 void set_value(T const& v)
157 { 96 {
158 typedef typename eina::alloc_to_c_traits<T>::c_type c_type; 97 typedef typename eina::alloc_to_c_traits<T>::c_type c_type;
@@ -167,14 +106,9 @@ struct promise_1_type : promise_common
167 } 106 }
168}; 107};
169 108
170template <> 109template <typename Progress>
171struct promise_1_type<void> : promise_common 110struct promise_1_type<void, Progress> : promise_progress<Progress>
172{ 111{
173 typedef promise_common _base_type;
174 using _base_type::_base_type;
175 using _base_type::swap;
176 using _base_type::set_exception;
177
178 void set_value() 112 void set_value()
179 { 113 {
180 efl_promise_value_set(this->_promise, nullptr, nullptr); 114 efl_promise_value_set(this->_promise, nullptr, nullptr);
@@ -184,19 +118,20 @@ struct promise_1_type<void> : promise_common
184} 118}
185 119
186template <typename T, typename Progress = void> 120template <typename T, typename Progress = void>
187struct promise : private _impl::promise_1_type<T> 121struct promise : private _impl::promise_1_type<T, Progress>
188{ 122{
189 typedef _impl::promise_1_type<T> _base_type; 123 typedef _impl::promise_1_type<T, Progress> _base_type;
190 using _base_type::_base_type; 124 using _base_type::_base_type;
191 using _base_type::set_value; 125 using _base_type::set_value;
126 using _base_type::set_progress;
192 using _base_type::set_exception; 127 using _base_type::set_exception;
193 128
194 shared_future<T> get_future() 129 shared_future<T, progress<Progress>> get_future()
195 { 130 {
196 return shared_future<T>{ ::efl_ref( ::efl_promise_future_get(this->_promise)) }; 131 return shared_future<T, progress<Progress>>{ ::efl_ref( ::efl_promise_future_get(this->_promise)) };
197 } 132 }
198 133
199 void swap(promise<T>& other) 134 void swap(promise<T, progress<Progress>>& other)
200 { 135 {
201 _base_type::swap(other); 136 _base_type::swap(other);
202 } 137 }
diff --git a/src/bindings/cxx/eo_cxx/eo_promise_meta.hh b/src/bindings/cxx/eo_cxx/eo_promise_meta.hh
index 18b37d793a..aa2894fd2c 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;
13template <typename...Args> 13template <typename...Args>
14struct shared_race_future; 14struct shared_race_future;
15 15
16template <typename T>
17struct progress;
18
16namespace _impl { 19namespace _impl {
17 20
21template <typename T>
22struct is_progress : std::false_type {};
23
24template <typename T>
25struct is_progress<progress<T>> : std::true_type {};
26
27template <typename L, typename R>
28struct is_progress_param_compatible : std::false_type {};
29
30template <typename T>
31struct is_progress_param_compatible<T, T> : std::true_type {};
32
33template <>
34struct is_progress_param_compatible<void, progress<void>> : std::true_type {};
35
36template <>
37struct is_progress_param_compatible<progress<void>, void> : std::true_type {};
38
39template <typename...Args>
40struct progress_param : std::conditional
41 <is_progress<typename std::tuple_element<sizeof...(Args) - 1, std::tuple<Args...>>::type>::value
42 , typename std::tuple_element<sizeof...(Args) - 1, std::tuple<Args...>>::type
43 , void>
44{
45};
46
47template <typename T>
48struct progress_type;
49
50template <typename T>
51struct progress_type<progress<T>>
52{
53 typedef T type;
54};
55
56template <>
57struct progress_type<void>
58{
59 typedef void type;
60};
61
18template <typename...Futures> 62template <typename...Futures>
19struct all_result_type; 63struct all_result_type;
20 64
diff --git a/src/tests/eo_cxx/eo_cxx_test_promise.cc b/src/tests/eo_cxx/eo_cxx_test_promise.cc
index 01b45c7bb2..3edc5e8852 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)
930} 930}
931END_TEST 931END_TEST
932 932
933template <typename T>
934void eo_cxx_promise_progress_set_impl()
935{
936 ecore_init();
937
938 {
939 efl::promise<int, T> promise;
940 efl::shared_future<int, efl::progress<T>> f = promise.get_future();
941
942 on_progress
943 (f, [&] (T const& value)
944 {
945 ck_assert_int_eq(value, test_value_get<T>::get());
946 ecore_main_loop_quit();
947 });
948
949 std::thread thread
950 ([&] {
951 efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start
952 efl::ecore::main_loop_thread_safe_call_async
953 ([&]
954 {
955 promise.set_progress(test_value_get<T>::get());
956 });
957 });
958
959 ecore_main_loop_begin();
960
961 thread.join();
962 }
963 ecore_shutdown();
964}
965
966START_TEST(eo_cxx_promise_progress_set)
967{
968 eo_cxx_promise_progress_set_impl<int>();
969}
970END_TEST
971
933void 972void
934eo_cxx_test_promise(TCase* tc) 973eo_cxx_test_promise(TCase* tc)
935{ 974{
@@ -958,4 +997,5 @@ eo_cxx_test_promise(TCase* tc)
958 997
959 tcase_add_test(tc, eo_cxx_promise_construct_and_destroy); 998 tcase_add_test(tc, eo_cxx_promise_construct_and_destroy);
960 tcase_add_test(tc, eo_cxx_promise_value_set); 999 tcase_add_test(tc, eo_cxx_promise_value_set);
1000 tcase_add_test(tc, eo_cxx_promise_progress_set);
961} 1001}