Efl_Object: make main domain accessible in Eina_Coro.
Currently Eina_Coro is implemented with actual threads, that barf Eo checkings and makes main thread objects unusuable. Since this is an implementation detail, let's use Eina_Coro hooks to adopt the main domain and return when it's done... The user doesn't see this, it's transparent.
This commit is contained in:
parent
d10a35628c
commit
109bf1b387
|
@ -146,6 +146,7 @@ tests/eo/suite/eo_test_class_behaviour_errors.c \
|
|||
tests/eo/suite/eo_test_call_errors.c \
|
||||
tests/eo/suite/eo_test_general.c \
|
||||
tests/eo/suite/eo_test_value.c \
|
||||
tests/eo/suite/eo_test_coro.c \
|
||||
tests/eo/suite/eo_test_event.c \
|
||||
tests/eo/suite/eo_test_threaded_calls.c \
|
||||
tests/eo/suite/eo_test_init.c
|
||||
|
|
|
@ -68,3 +68,5 @@ struct @extern Eina.Future; [[Eina Future handles]]
|
|||
struct @extern Eina.Future.Scheduler; [[This struct is used as a bridge between Eina and the future scheduler.
|
||||
By using the provided functions Eina can schedule futures resolutions,
|
||||
rejections and cancelations to a safe context.]]
|
||||
|
||||
struct @extern Eina.Coro; [[Eina Coro (coroutine) handle.]]
|
||||
|
|
126
src/lib/eo/eo.c
126
src/lib/eo/eo.c
|
@ -2137,6 +2137,118 @@ _eo_table_del_cb(void *in)
|
|||
* This is used by the gdb debug helper script */
|
||||
Eo_Id_Data *_eo_gdb_main_domain = NULL;
|
||||
|
||||
typedef struct _Eo_Coro_Hook_Data
|
||||
{
|
||||
EINA_INLIST;
|
||||
const Eina_Coro *coro;
|
||||
Efl_Domain_Data *domain_data;
|
||||
Efl_Id_Domain return_domain;
|
||||
} Eo_Coro_Hook_Data;
|
||||
|
||||
static Eina_Inlist *_eo_coro_hook_data = NULL;
|
||||
static Eina_Lock _eo_coro_hook_data_lock;
|
||||
|
||||
/* Flow:
|
||||
*
|
||||
* main_exit -> coro_enter -> coro_exit -> main_enter
|
||||
*
|
||||
* main_exit: efl_domain_data_get()
|
||||
* coro_enter: efl_domain_data_adopt()
|
||||
* coro_exit: efl_domain_data_return()
|
||||
* main_enter: remove from list
|
||||
*/
|
||||
|
||||
static Eo_Coro_Hook_Data *
|
||||
_eo_coro_hook_data_find_unlocked(const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d;
|
||||
|
||||
EINA_INLIST_FOREACH(_eo_coro_hook_data, d)
|
||||
{
|
||||
if (d->coro == coro)
|
||||
{
|
||||
if (_eo_coro_hook_data != EINA_INLIST_GET(d))
|
||||
_eo_coro_hook_data = eina_inlist_promote(_eo_coro_hook_data,
|
||||
EINA_INLIST_GET(d));
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Eo_Coro_Hook_Data *
|
||||
_eo_coro_hook_data_find(const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d;
|
||||
|
||||
eina_lock_take(&_eo_coro_hook_data_lock);
|
||||
d = _eo_coro_hook_data_find_unlocked(coro);
|
||||
eina_lock_release(&_eo_coro_hook_data_lock);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eo_coro_hook_main_exit(void *data EINA_UNUSED, const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d = malloc(sizeof(Eo_Coro_Hook_Data));
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(d, EINA_FALSE);
|
||||
|
||||
d->coro = coro;
|
||||
d->domain_data = efl_domain_data_get();
|
||||
d->return_domain = EFL_ID_DOMAIN_INVALID;
|
||||
|
||||
eina_lock_take(&_eo_coro_hook_data_lock);
|
||||
_eo_coro_hook_data = eina_inlist_prepend(_eo_coro_hook_data, EINA_INLIST_GET(d));
|
||||
eina_lock_release(&_eo_coro_hook_data_lock);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_eo_coro_hook_main_enter(void *data EINA_UNUSED, const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d;
|
||||
|
||||
eina_lock_take(&_eo_coro_hook_data_lock);
|
||||
d = _eo_coro_hook_data_find_unlocked(coro);
|
||||
if (d)
|
||||
_eo_coro_hook_data = eina_inlist_remove(_eo_coro_hook_data, EINA_INLIST_GET(d));
|
||||
eina_lock_release(&_eo_coro_hook_data_lock);
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(d); // just to print-out unexpected error.
|
||||
free(d);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_eo_coro_hook_coro_enter(void *data EINA_UNUSED, const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d = _eo_coro_hook_data_find(coro);
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(d, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(d->domain_data, EINA_FALSE);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(d->return_domain != EFL_ID_DOMAIN_INVALID, EINA_FALSE);
|
||||
|
||||
d->return_domain = efl_domain_data_adopt(d->domain_data);
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(d->return_domain == EFL_ID_DOMAIN_INVALID, EINA_FALSE);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_eo_coro_hook_coro_exit(void *data EINA_UNUSED, const Eina_Coro *coro)
|
||||
{
|
||||
Eo_Coro_Hook_Data *d = _eo_coro_hook_data_find(coro);
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN(d);
|
||||
EINA_SAFETY_ON_NULL_RETURN(d->domain_data);
|
||||
EINA_SAFETY_ON_TRUE_RETURN(d->return_domain == EFL_ID_DOMAIN_INVALID);
|
||||
|
||||
efl_domain_data_return(d->return_domain);
|
||||
d->domain_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
EAPI Eina_Bool
|
||||
efl_object_init(void)
|
||||
{
|
||||
|
@ -2229,6 +2341,13 @@ efl_object_init(void)
|
|||
|
||||
_efl_add_fallback_init();
|
||||
|
||||
eina_lock_new(&_eo_coro_hook_data_lock);
|
||||
eina_coro_hook_add(_eo_coro_hook_coro_enter,
|
||||
_eo_coro_hook_coro_exit,
|
||||
_eo_coro_hook_main_enter,
|
||||
_eo_coro_hook_main_exit,
|
||||
NULL);
|
||||
|
||||
eina_log_timing(_eo_log_dom,
|
||||
EINA_LOG_STATE_STOP,
|
||||
EINA_LOG_STATE_INIT);
|
||||
|
@ -2252,6 +2371,13 @@ efl_object_shutdown(void)
|
|||
EINA_LOG_STATE_START,
|
||||
EINA_LOG_STATE_SHUTDOWN);
|
||||
|
||||
eina_coro_hook_del(_eo_coro_hook_coro_enter,
|
||||
_eo_coro_hook_coro_exit,
|
||||
_eo_coro_hook_main_enter,
|
||||
_eo_coro_hook_main_exit,
|
||||
NULL);
|
||||
eina_lock_free(&_eo_coro_hook_data_lock);
|
||||
|
||||
_efl_add_fallback_shutdown();
|
||||
|
||||
efl_future_shutdown();
|
||||
|
|
|
@ -12,6 +12,7 @@ static const Efl_Test_Case etc[] = {
|
|||
{ "Eo class behaviour errors", eo_test_class_behaviour_errors },
|
||||
{ "Eo call errors", eo_test_call_errors },
|
||||
{ "Eo eina value", eo_test_value },
|
||||
{ "Eo eina coroutines", eo_test_coro },
|
||||
{ "Eo threaded eo calls", eo_test_threaded_calls },
|
||||
{ "Eo event calls", eo_test_event},
|
||||
{ NULL, NULL }
|
||||
|
|
|
@ -9,6 +9,7 @@ void eo_test_class_errors(TCase *tc);
|
|||
void eo_test_class_behaviour_errors(TCase *tc);
|
||||
void eo_test_call_errors(TCase *tc);
|
||||
void eo_test_value(TCase *tc);
|
||||
void eo_test_coro(TCase *tc);
|
||||
void eo_test_threaded_calls(TCase *tc);
|
||||
void eo_test_event(TCase *tc);
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Eo.h>
|
||||
|
||||
#include "eo_suite.h"
|
||||
#include "eo_test_class_simple.h"
|
||||
|
||||
#define RETVAL ((void *)0x1234)
|
||||
|
||||
static const void *
|
||||
func(void *data, Eina_Bool canceled EINA_UNUSED, Eina_Coro *coro EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
|
||||
fail_unless(efl_ref(obj)); // if efl_domain_data is wrong, this fails...
|
||||
|
||||
return RETVAL;
|
||||
}
|
||||
|
||||
START_TEST(eo_coro)
|
||||
{
|
||||
Eo *obj;
|
||||
Eina_Coro *coro;
|
||||
void *result;
|
||||
|
||||
efl_object_init();
|
||||
|
||||
obj = efl_add(SIMPLE_CLASS, NULL);
|
||||
fail_unless(obj);
|
||||
|
||||
coro = eina_coro_new(func, obj, EINA_CORO_STACK_SIZE_DEFAULT);
|
||||
fail_unless(coro);
|
||||
|
||||
fail_if(eina_coro_run(&coro, &result, NULL)); // doesn't yield, so should finish
|
||||
ck_assert_ptr_eq(result, RETVAL);
|
||||
|
||||
ck_assert_int_eq(efl_ref_get(obj), 2);
|
||||
efl_unref(obj);
|
||||
efl_unref(obj);
|
||||
|
||||
efl_object_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void eo_test_coro(TCase *tc)
|
||||
{
|
||||
tcase_add_test(tc, eo_coro);
|
||||
}
|
Loading…
Reference in New Issue