aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-04-01 15:37:42 -0300
committerCedric Bail <cedric@osg.samsung.com>2016-04-05 11:35:12 -0700
commit887608e146b8e3952974182b2cc5a7009a711db5 (patch)
tree69b1471411a09bb9e21db93bdc29d8ff5f64ab9d /src
parenteina: add tests for promises (diff)
downloadefl-887608e146b8e3952974182b2cc5a7009a711db5.tar.gz
ecore: add promise for Ecore_Thread
Add ecore_thread_promise_run function that returns a Promise and runs function in another thread which you can set the value on a Eina_Promise_Owner. Eina_Promise* promise; Ecore_Thread* thread = ecore_thread_promise_run ( &function_heavy, &cancellation_function, private_data, sizeof(ValueType), &promise); This calls function_heavy on another thread and returns the Ecore_Thread and a Eina_Promise as an out-parameter. Signed-off-by: Cedric Bail <cedric@osg.samsung.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Ecore.am1
-rw-r--r--src/lib/ecore/Ecore_Common.h20
-rw-r--r--src/lib/ecore/ecore_thread_promise.c137
3 files changed, 158 insertions, 0 deletions
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index e5d5efc981..084256eea3 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -66,6 +66,7 @@ lib/ecore/ecore_poller.c \
lib/ecore/ecore_time.c \
lib/ecore/ecore_timer.c \
lib/ecore/ecore_thread.c \
+lib/ecore/ecore_thread_promise.c \
lib/ecore/ecore_throttle.c \
lib/ecore/ecore_exe.c \
lib/ecore/ecore_exe_private.h \
diff --git a/src/lib/ecore/Ecore_Common.h b/src/lib/ecore/Ecore_Common.h
index fe2c5c9012..711ea7a07c 100644
--- a/src/lib/ecore/Ecore_Common.h
+++ b/src/lib/ecore/Ecore_Common.h
@@ -3089,6 +3089,26 @@ typedef Eo Ecore_Job; /**< A job handle */
* @}
*/
+
+#ifdef EFL_BETA_API_SUPPORT
+
+/*
+ * @brief Function callback type for when creating Ecore_Thread that
+ * uses Ecore_Promise for communication
+ */
+typedef void(*Ecore_Thread_Promise_Cb)(const void* data, Eina_Promise_Owner* promise, Ecore_Thread* thread);
+
+/*
+ * @brief Function that instantiates a Ecore_Promise and automatically
+ * executes func_blocking callback function in another thread
+ */
+EAPI Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_heavy,
+ Ecore_Thread_Promise_Cb func_cancel,
+ const void* data, size_t value_size,
+ Eina_Promise** promise);
+
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/ecore/ecore_thread_promise.c b/src/lib/ecore/ecore_thread_promise.c
new file mode 100644
index 0000000000..dbc3ce9bbd
--- /dev/null
+++ b/src/lib/ecore/ecore_thread_promise.c
@@ -0,0 +1,137 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.h>
+#include <Ecore.h>
+
+#include <assert.h>
+
+struct _Ecore_Thread_Data
+{
+ Ecore_Thread_Promise_Cb func_blocking;
+ Ecore_Thread_Promise_Cb func_cancel;
+ void const* data;
+ Ecore_Thread* thread;
+};
+typedef struct _Ecore_Thread_Data _Ecore_Thread_Data;
+
+struct _Ecore_Thread_Promise_Owner
+{
+ Eina_Promise_Owner owner_vtable;
+ Eina_Promise_Owner* eina_owner;
+ _Ecore_Thread_Data thread_callback_data;
+};
+typedef struct _Ecore_Thread_Promise_Owner _Ecore_Thread_Promise_Owner;
+
+static void _ecore_promise_thread_end(void* data, Ecore_Thread* thread EINA_UNUSED)
+{
+ _Ecore_Thread_Promise_Owner* p = data;
+ if(!eina_promise_owner_pending_is(p->eina_owner))
+ {
+ eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
+ eina_promise_owner_default_call_then(p->eina_owner);
+ }
+ else
+ {
+ eina_promise_owner_default_manual_then_set(p->eina_owner, EINA_FALSE);
+ }
+}
+
+static void
+_ecore_promise_thread_blocking(void* data, Ecore_Thread* thread EINA_UNUSED)
+{
+ _Ecore_Thread_Promise_Owner* promise = data;
+ (promise->thread_callback_data.func_blocking)(promise->thread_callback_data.data, &promise->owner_vtable, thread);
+}
+
+static void _ecore_promise_thread_notify(void* data, Ecore_Thread* thread EINA_UNUSED, void* msg_data)
+{
+ _Ecore_Thread_Promise_Owner* promise = data;
+ eina_promise_owner_progress(promise->eina_owner, msg_data);
+}
+
+static void _ecore_promise_cancel(void* data, Eina_Promise_Owner* promise EINA_UNUSED)
+{
+ _Ecore_Thread_Promise_Owner* priv = data;
+ (priv->thread_callback_data.func_cancel)(priv->thread_callback_data.data, &priv->owner_vtable,
+ priv->thread_callback_data.thread);
+}
+
+static void _ecore_promise_thread_cancel(void* data, Ecore_Thread* thread EINA_UNUSED)
+{
+ _Ecore_Thread_Promise_Owner* owner = data;
+ Eina_Promise* promise;
+
+ promise = eina_promise_owner_promise_get(owner->eina_owner);
+ eina_promise_cancel(promise);
+}
+
+static void* _ecore_promise_owner_buffer_get(_Ecore_Thread_Promise_Owner* promise)
+{
+ return promise->eina_owner->buffer_get(promise->eina_owner);
+}
+static size_t _ecore_promise_owner_value_size_get(_Ecore_Thread_Promise_Owner const* promise)
+{
+ return promise->eina_owner->value_size_get(promise->eina_owner);
+}
+static void _ecore_promise_owner_value_set(_Ecore_Thread_Promise_Owner* promise, void* data, Eina_Promise_Free_Cb free)
+{
+ promise->eina_owner->value_set(promise->eina_owner, data, free);
+}
+static void _ecore_promise_owner_error_set(_Ecore_Thread_Promise_Owner* promise, Eina_Error error)
+{
+ promise->eina_owner->error_set(promise->eina_owner, error);
+}
+static Eina_Bool _ecore_promise_owner_pending_is(_Ecore_Thread_Promise_Owner const* promise)
+{
+ return promise->eina_owner->pending_is(promise->eina_owner);
+}
+static Eina_Bool _ecore_promise_owner_cancelled_is(_Ecore_Thread_Promise_Owner const* promise)
+{
+ return promise->eina_owner->cancelled_is(promise->eina_owner);
+}
+static Eina_Promise* _ecore_thread_promise_owner_promise_get(_Ecore_Thread_Promise_Owner* promise)
+{
+ return promise->eina_owner->promise_get(promise->eina_owner);
+}
+static void _ecore_thread_promise_owner_progress(_Ecore_Thread_Promise_Owner* promise, void* data)
+{
+ ecore_thread_feedback(promise->thread_callback_data.thread, data);
+}
+
+Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_blocking,
+ Ecore_Thread_Promise_Cb func_cancel,
+ const void* data, size_t value_size,
+ Eina_Promise** promise)
+{
+ _Ecore_Thread_Promise_Owner* priv;
+
+ priv = malloc(sizeof(_Ecore_Thread_Promise_Owner));
+
+ priv->eina_owner = eina_promise_default_add(value_size);
+
+ priv->owner_vtable.version = EINA_PROMISE_VERSION;
+ priv->owner_vtable.value_set = EINA_FUNC_PROMISE_OWNER_VALUE_SET(&_ecore_promise_owner_value_set);
+ priv->owner_vtable.error_set = EINA_FUNC_PROMISE_OWNER_ERROR_SET(&_ecore_promise_owner_error_set);
+ priv->owner_vtable.buffer_get = EINA_FUNC_PROMISE_OWNER_BUFFER_GET(&_ecore_promise_owner_buffer_get);
+ priv->owner_vtable.value_size_get = EINA_FUNC_PROMISE_OWNER_VALUE_SIZE_GET(&_ecore_promise_owner_value_size_get);
+ priv->owner_vtable.promise_get = EINA_FUNC_PROMISE_OWNER_PROMISE_GET(&_ecore_thread_promise_owner_promise_get);
+ priv->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(&_ecore_promise_owner_pending_is);
+ priv->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(&_ecore_promise_owner_cancelled_is);
+ priv->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(&_ecore_thread_promise_owner_progress);
+
+ priv->thread_callback_data.data = data;
+ priv->thread_callback_data.func_blocking = func_blocking;
+ priv->thread_callback_data.func_cancel = func_cancel;
+ eina_promise_owner_default_manual_then_set(priv->eina_owner, EINA_TRUE);
+ if(func_cancel)
+ eina_promise_owner_default_cancel_cb_add(priv->eina_owner, &_ecore_promise_cancel, priv, NULL);
+ priv->thread_callback_data.thread =
+ ecore_thread_feedback_run(&_ecore_promise_thread_blocking, &_ecore_promise_thread_notify,
+ &_ecore_promise_thread_end, &_ecore_promise_thread_cancel, priv,
+ EINA_FALSE);
+ if(promise)
+ *promise = priv->eina_owner->promise_get(priv->eina_owner);
+ return priv->thread_callback_data.thread;
+}