Eo: Add eo_finalize. A func that's called at the end of eo_add.

This function lets you hook at the end of eo_add and override it for a
class. This is essentially the first step towards killing custom
constructors. Instead of having a custom constructor, you should just
do:
eo_add(CLASS, parent, a_set(3), b_set("eou"));
eo_constructor is called at the beginning for pre-init things.
eo_finalize is called at the end, for actually finalizing and doing
things. This cleans up the API and possibly saves a lot of things that
would have been stupid and slow in the past, like loading an elm widget
with an existing theme, and then changing the theme.

** This breaks Eo ABI, please recompile elementary and everything else that
creates eo objects.

@feature
This commit is contained in:
Tom Hacohen 2014-05-30 11:17:36 +01:00
parent a3e58b7618
commit f92e5d50f9
6 changed files with 67 additions and 8 deletions

View File

@ -631,7 +631,7 @@ EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
eo_do(_tmp_obj, \
eo_constructor(); \
__VA_ARGS__; \
_tmp_obj = _eo_add_internal_end(__FILE__, __LINE__, _tmp_obj); \
_tmp_obj = eo_finalize(); \
); \
_tmp_obj; \
})
@ -652,13 +652,12 @@ EAPI void eo_error_set_internal(const Eo *obj, const char *file, int line);
Eo *_tmp_obj = _eo_add_internal_start(__FILE__, __LINE__, _tmp_klass, parent); \
eo_do(_tmp_obj, \
__VA_ARGS__; \
_tmp_obj = _eo_add_internal_end(__FILE__, __LINE__, _tmp_obj); \
_tmp_obj = eo_finalize(); \
); \
_tmp_obj; \
})
EAPI Eo * _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent);
EAPI Eo * _eo_add_internal_end(const char *file, int line, const Eo *obj);
/**
* @brief Get a pointer to the data of an object for a specific class.
@ -1103,6 +1102,15 @@ EAPI void eo_constructor(void);
*/
EAPI void eo_destructor(void);
/**
* @brief Called at the end of #eo_add.
*
* Should not be called, just overridden.
*
* @see #eo_add
*/
EAPI Eo *eo_finalize(void);
/**
* @addtogroup Eo_Events Eo's Event Handling
* @{

View File

@ -926,8 +926,8 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
return _eo_id_get(obj);
}
EAPI Eo *
_eo_add_internal_end(const char *file, int line, const Eo *eo_id)
Eo *
_eo_add_internal_end(Eo *eo_id)
{
Eo_Stack_Frame *fptr;
Eo_Call_Stack *stack = _eo_call_stack_get();
@ -936,7 +936,7 @@ _eo_add_internal_end(const char *file, int line, const Eo *eo_id)
if ((fptr == NULL) || (fptr->eo_id != eo_id))
{
ERR("in %s:%d - Something very wrong happend to the call stack.", file, line);
ERR("Something very wrong happend to the call stack.");
return NULL;
}
@ -947,8 +947,8 @@ _eo_add_internal_end(const char *file, int line, const Eo *eo_id)
{
const _Eo_Class *klass = (fptr->cur_klass) ?
fptr->cur_klass : fptr->o.obj->klass;
ERR("in %s:%d: Object of class '%s' - Not all of the object constructors have been executed.",
file, line, klass->desc->name);
ERR("Object of class '%s' - Not all of the object constructors have been executed.",
klass->desc->name);
/* Unref twice, once for the ref in _eo_add_internal_start, and once for the basic object ref. */
_eo_unref(fptr->o.obj);
_eo_unref(fptr->o.obj);

View File

@ -77,6 +77,10 @@ Prevents event callbacks from being called for the object. */
/*@ Call the object's destructor.
Should not be used with #eo_do. Only use it with #eo_do_super. */
}
finalize {
/*@ Called at the end of #eo_add. Should not be called, just overridden. */
return Eo *; /*@ The new object created, can be NULL if the finalize func decided to abort (though it should free the created object on it's own). */
}
key_data_set {
/*@ Set generic data to object. */
params {

View File

@ -1007,6 +1007,13 @@ _destructor(Eo *obj, void *class_data)
}
EAPI EO_VOID_FUNC_BODY(eo_destructor);
static Eo *
_finalize(Eo *obj, void *class_data EINA_UNUSED)
{
return _eo_add_internal_end(obj);
}
EAPI EO_FUNC_BODY(eo_finalize, Eo *, NULL);
static void
_class_constructor(Eo_Class *klass EINA_UNUSED)
{
@ -1023,6 +1030,7 @@ _class_destructor(Eo_Class *klass EINA_UNUSED)
static Eo_Op_Description op_descs [] = {
EO_OP_FUNC(eo_constructor, _constructor, "Constructor."),
EO_OP_FUNC(eo_destructor, _destructor, "Destructor."),
EO_OP_FUNC(eo_finalize, _finalize, "Finalize object creation."),
EO_OP_FUNC(eo_parent_set, _parent_set, "Set parent."),
EO_OP_FUNC(eo_parent_get, _parent_get, "Get parent."),
EO_OP_FUNC(eo_children_iterator_new, _children_iterator_new, "Get Children Iterator."),

View File

@ -73,6 +73,7 @@ static inline void _eo_id_release(const Eo_Id obj_id);
/* Free all the entries and the tables */
static inline void _eo_free_ids_tables(void);
Eo *_eo_add_internal_end(Eo *obj);
void _eo_condtor_done(Eo *obj);
struct _Eo_Base

View File

@ -873,6 +873,43 @@ START_TEST(eo_pointers_indirection)
}
END_TEST
static Eo *
_eo_add_failures_finalize(Eo *obj EINA_UNUSED, void *class_data EINA_UNUSED)
{
return NULL;
}
static Eo_Op_Description _eo_add_failures_op_descs[] = {
EO_OP_FUNC_OVERRIDE(eo_finalize, _eo_add_failures_finalize),
EO_OP_SENTINEL
};
START_TEST(eo_add_failures)
{
eo_init();
static const Eo_Class_Description class_desc = {
EO_VERSION,
"Simple2",
EO_CLASS_TYPE_REGULAR,
EO_CLASS_DESCRIPTION_OPS(_eo_add_failures_op_descs),
NULL,
0,
NULL,
NULL
};
const Eo_Class *klass = eo_class_new(&class_desc, EO_CLASS, NULL);
Eo *obj = eo_add(klass, NULL);
fail_if(obj);
eo_shutdown();
}
END_TEST
void eo_test_general(TCase *tc)
{
tcase_add_test(tc, eo_simple);
@ -889,4 +926,5 @@ void eo_test_general(TCase *tc)
tcase_add_test(tc, eo_multiple_do);
tcase_add_test(tc, eo_add_do_and_custom);
tcase_add_test(tc, eo_pointers_indirection);
tcase_add_test(tc, eo_add_failures);
}