forked from enlightenment/efl
ecore: add a prototype ecore_thread helper with Efl_Promise/Efl_Future coupled.
This commit is contained in:
parent
c4c95adc6b
commit
6c514dddb3
|
@ -3124,6 +3124,10 @@ EAPI Ecore_Thread* ecore_thread_promise_run(Ecore_Thread_Promise_Cb func_heavy,
|
||||||
const void* data,
|
const void* data,
|
||||||
Eina_Promise** promise);
|
Eina_Promise** promise);
|
||||||
|
|
||||||
|
typedef void (*Ecore_Thread_Future_Cb)(const void *data, Eo *promise, Ecore_Thread *thread);
|
||||||
|
|
||||||
|
EAPI Efl_Future *ecore_thread_future_run(Ecore_Thread_Future_Cb heavy, const void *data, Eina_Free_Cb free_cb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1458,3 +1458,180 @@ ecore_thread_global_data_wait(const char *key,
|
||||||
if (ret) return ret->data;
|
if (ret) return ret->data;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _Ecore_Thread_Set Ecore_Thread_Set;
|
||||||
|
struct _Ecore_Thread_Set
|
||||||
|
{
|
||||||
|
Eo *obj;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
void *v;
|
||||||
|
Eina_Free_Cb free_cb;
|
||||||
|
} value;
|
||||||
|
Eina_Error error;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
Eina_Bool success;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_main_loop_set(void *data)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Set *dt = data;
|
||||||
|
|
||||||
|
if (dt->success)
|
||||||
|
efl_promise_value_set(efl_super(dt->obj, EFL_OBJECT_OVERRIDE_CLASS),
|
||||||
|
dt->u.value.v, dt->u.value.free_cb);
|
||||||
|
else
|
||||||
|
efl_promise_failed_set(efl_super(dt->obj, EFL_OBJECT_OVERRIDE_CLASS),
|
||||||
|
dt->u.error);
|
||||||
|
|
||||||
|
efl_unref(dt->obj);
|
||||||
|
free(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Ecore_Thread_Set *
|
||||||
|
_ecore_thread_set_new(Eo *obj)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Set *dt;
|
||||||
|
|
||||||
|
dt = calloc(1, sizeof (Ecore_Thread_Set));
|
||||||
|
if (!dt) return NULL;
|
||||||
|
|
||||||
|
dt->obj = efl_ref(obj);
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_value_set(Eo *obj, const void *data EINA_UNUSED, void *v, Eina_Free_Cb free_cb)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Set *dt;
|
||||||
|
|
||||||
|
dt = _ecore_thread_set_new(obj);
|
||||||
|
if (!dt) return ;
|
||||||
|
|
||||||
|
dt->success = EINA_TRUE;
|
||||||
|
dt->u.value.v = v;
|
||||||
|
dt->u.value.free_cb = free_cb;
|
||||||
|
|
||||||
|
ecore_main_loop_thread_safe_call_async(_ecore_thread_main_loop_set, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_failed_set(Eo *obj, const void *data EINA_UNUSED, Eina_Error err)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Set *dt;
|
||||||
|
|
||||||
|
dt = _ecore_thread_set_new(obj);
|
||||||
|
if (!dt) return ;
|
||||||
|
|
||||||
|
dt->success = EINA_FALSE;
|
||||||
|
dt->u.error = err;
|
||||||
|
|
||||||
|
ecore_main_loop_thread_safe_call_async(_ecore_thread_main_loop_set, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _Ecore_Thread_Progress Ecore_Thread_Progress;
|
||||||
|
struct _Ecore_Thread_Progress
|
||||||
|
{
|
||||||
|
Eo *obj;
|
||||||
|
const void *p;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_ecore_thread_progress_sync(void *data)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Progress *p = data;
|
||||||
|
|
||||||
|
efl_promise_progress_set(efl_super(p->obj, EFL_OBJECT_OVERRIDE_CLASS), p->p);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_progress_set(Eo *obj, const void *data EINA_UNUSED, const void *p)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Progress ip = { efl_ref(obj), p };
|
||||||
|
|
||||||
|
ecore_main_loop_thread_safe_call_sync(_ecore_thread_progress_sync, &ip);
|
||||||
|
efl_unref(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_future_heavy(void *dp, Ecore_Thread *thread)
|
||||||
|
{
|
||||||
|
Ecore_Thread_Future_Cb heavy;
|
||||||
|
const void *data;
|
||||||
|
Eo *p = dp;
|
||||||
|
|
||||||
|
heavy = efl_key_data_get(p, "_ecore_thread.heavy");
|
||||||
|
data = efl_key_data_get(p, "_ecore_thread.data");
|
||||||
|
|
||||||
|
heavy(data, p, thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_future_end(void *dp, Ecore_Thread *thread EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Eina_Free_Cb free_cb;
|
||||||
|
void *data;
|
||||||
|
Eo *p = dp;
|
||||||
|
|
||||||
|
free_cb = efl_key_data_get(p, "_ecore_thread.free_cb");
|
||||||
|
data = efl_key_data_get(p, "_ecore_thread.data");
|
||||||
|
|
||||||
|
if (free_cb) free_cb(data);
|
||||||
|
efl_del(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ecore_thread_future_none(void *data, const Efl_Event *ev EINA_UNUSED)
|
||||||
|
{
|
||||||
|
Ecore_Thread *t = data;
|
||||||
|
|
||||||
|
// Cancelling thread if there is nobody listening on the promise anymore
|
||||||
|
ecore_thread_cancel(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAPI Efl_Future *
|
||||||
|
ecore_thread_future_run(Ecore_Thread_Future_Cb heavy, const void *data, Eina_Free_Cb free_cb)
|
||||||
|
{
|
||||||
|
Ecore_Thread *t;
|
||||||
|
Eo *p;
|
||||||
|
|
||||||
|
if (!heavy) return NULL;
|
||||||
|
|
||||||
|
EFL_OPS_DEFINE(thread_safe_call,
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_promise_value_set, _ecore_thread_value_set),
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_promise_failed_set, _ecore_thread_failed_set),
|
||||||
|
EFL_OBJECT_OP_FUNC(efl_promise_progress_set, _ecore_thread_progress_set));
|
||||||
|
|
||||||
|
efl_domain_current_push(EFL_ID_DOMAIN_SHARED);
|
||||||
|
|
||||||
|
efl_wref_add(efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()), &p);
|
||||||
|
if (!p) goto end;
|
||||||
|
|
||||||
|
efl_object_override(p, &thread_safe_call);
|
||||||
|
|
||||||
|
efl_key_data_set(p, "_ecore_thread.data", data);
|
||||||
|
efl_key_data_set(p, "_ecore_thread.free_cb", free_cb);
|
||||||
|
efl_key_data_set(p, "_ecore_thread.heavy", heavy);
|
||||||
|
|
||||||
|
t = ecore_thread_run(_ecore_thread_future_heavy,
|
||||||
|
_ecore_thread_future_end,
|
||||||
|
_ecore_thread_future_end,
|
||||||
|
p);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
efl_event_callback_add(p, EFL_PROMISE_EVENT_FUTURE_NONE, _ecore_thread_future_none, t);
|
||||||
|
efl_wref_del(p, &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
efl_domain_current_pop();
|
||||||
|
|
||||||
|
return p ? efl_promise_future_get(p) : NULL;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue