On Thu, 10 Mar 2016 16:07:58 +0000 Tom Hacohen <t...@osg.samsung.com> said:
> On 08/03/16 13:39, Tom Hacohen wrote: > > Hey, > > > > Wouldn't it better if the intercept function could return a value saying > > "actually, the object is good to go, just delete it normally", like in > > your example, if the object is already in the right thread, it should > > just delete immediately, no? > > To be honest, giving it a bit more thought I don't see how that is > useful. I think that it's an extreme corner case that is not worth the > trouble, and I'm very much against adding this kind of API because we > actually have uses for them. I'm talking about code using them. Adding > this won't break API so we can wait with adding it until when we > actually need it. actually it will be used soon - specifically for generic messages between lop objects. this is the only way to ensure "safe destruction" of an Eo * payload. > An alternative would be to deal with the cleanup in the destructor. So > you for example free data that is thread agnostic, and when you have > code that needs to be run in a specific loop, you can set manual free > and defer the cleanup to that thread, so most of the object is > destructed in the destructing thread, but the relevant parts are cleaned > in the correct thread. This is implemented per object and is much cleaner. this is far more complex than just queing the deletion as a whole on another thread. > I like it better, but even if we choose to go with the idea in this > commit, I'd say: revert it until needed. I talked to Felipe about it on > IRC and he agrees. see above. i added this because it will be needed soon. like in the coming weeks/months. > -- > Tom. > > > > > -- > > Tom > > > > On 08/03/16 08:33, Carsten Haitzler wrote: > >> raster pushed a commit to branch master. > >> > >> http://git.enlightenment.org/core/efl.git/commit/?id=3df71ab0f668967cf37813cc2322d1993a4d5db1 > >> > >> commit 3df71ab0f668967cf37813cc2322d1993a4d5db1 > >> Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com> > >> Date: Tue Mar 8 16:57:22 2016 +0900. > >> > >> eo del interceptor: add the ability to intercept deletions of eo > >> objects > >> > >> Imagine this. You have an object. You pass this object handle as a > >> message to another thread. Let's say it's not a UI object, so > >> something you might expect to be able to be accessed from multiple > >> threads. In order to keep the object alive you eo_ref() it when > >> placing the message on a queue and eo_unref() it once the message is > >> "done" in the other thread. If the original sender unref()ed the > >> object before the message is done, then the object will be destroyed > >> in the reciever thread. This is bad for objects "expecting" not to be > >> destroyed outside their owning thread. > >> > >> This allows thius situation to be fixed. A constructor in a class of > >> an object can set up a delete interceptor. For example if we have a > >> "loop ownership" class you multi-ple-inherit from/use as a mixin. > >> This class will set up the interceptor to ensure that on destruction if > >> pthread_self() != owning loop thread id, then add object to "delete > >> me" queue on the owning loop and wake it up. the owning loop thread > >> will wake up and then process this queue and delete the queued > >> objects nicely and safely within the "owning context". > >> > >> This can also be used in this same manner to defer deletion within a > >> loop "until later" in the same delete_me queue. > >> > >> You can even use this as a caching mechanism for objects to prevernt > >> their actual destruction and instead place them in a cached area to > >> be picked from at a later date. > >> > >> The uses are many for this and this is a basic building block for > >> future EFL features like generic messages where a message payload > >> could be an eo object and thus the above loop onwership issue can > >> happen and needs fixing. > >> > >> This adds APIs, implementation, documentation (doxy reference) and > >> tests. > >> > >> @feature > >> --- > >> src/lib/eo/Eo.h | 58 ++++++++++++++++++++++++++++++ > >> ++++++ src/lib/eo/eo.c | 16 ++++++++++ > >> src/lib/eo/eo_private.h | 9 ++++++ > >> src/tests/eo/suite/eo_test_general.c | 55 ++++++++++++++++++++++++++++++ > >> ++++ 4 files changed, 138 insertions(+) > >> > >> diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h > >> index cf10bb3..4bfae97 100644 > >> --- a/src/lib/eo/Eo.h > >> +++ b/src/lib/eo/Eo.h > >> @@ -166,6 +166,16 @@ typedef struct _Eo_Event Eo_Event; > >> */ > >> typedef Eina_Bool (*Eo_Event_Cb)(void *data, const Eo_Event *event); > >> > >> +/** > >> + * @typedef Eo_Del_Intercept > >> + * > >> + * A function to be called on object deletion/destruction instead of > >> normal > >> + * destruction taking place. > >> + * > >> + * @param obj_id The object needing destruction > >> + */ > >> +typedef void (*Eo_Del_Intercept) (Eo *obj_id); > >> + > >> #include "eo_base.eo.h" > >> #define EO_CLASS EO_BASE_CLASS > >> > >> @@ -787,6 +797,54 @@ EAPI void eo_unref(const Eo *obj); > >> EAPI int eo_ref_get(const Eo *obj); > >> > >> /** > >> + * @brief Set a deletion interceptor function > >> + * @param obj The object to set the interceptor on > >> + * @param del_intercept_func The interceptor function to call > >> + * > >> + * This sets the function @p del_intercept_func to be called when an > >> object > >> + * is about to go from a reference count of 1 to 0, thus triggering actual > >> + * destruction of the object. Instead of going to a reference count of 0 > >> and > >> + * being destroyed, the object will stay alive with a reference count of 1 > >> + * and this intercept function will be called instead. It is the job of > >> + * this interceptor function to handle any further deletion of of the > >> object > >> + * from here. > >> + * > >> + * Note that by default objects have no interceptor function set, and thus > >> + * will be destroyed as normal. To return an object to this state, simply > >> + * set the @p del_intercept_func to NULL which is the default. > >> + * > >> + * A good use for this feature is to ensure an object is destroyed by its > >> + * owning main loop and not in a foreign loop. This makes it possible to > >> + * safely unrefor delete objects from any loop as an interceptor can be > >> set > >> + * on an object that will abort destruction and instead queue the object > >> + * on its owning loop to be destroyed at some time in the future and now > >> + * set the intercept function to NULL so it is not called again on the > >> next > >> + * "real deletion". > >> + * > >> + * @see eo_del_intercept_get() > >> + * @see eo_unref() > >> + * @see eo_del() > >> + */ > >> +EAPI void eo_del_intercept_set(Eo *obj, Eo_Del_Intercept > >> del_intercept_func); + > >> +/** > >> + * @brief Get the deletion interceptor function > >> + * @param obj The object to get the interceptor of > >> + * @return The intercept function or NULL if none is set. > >> + * > >> + * This returns the interceptor function set by eo_del_intercept_set(). > >> Note > >> + * that objects by default have no interceptor (NULL) set, but certain > >> + * classes may set one up in a constructor, so it is important to be able > >> + * to get the interceptor function to know if this has happend and > >> + * if you want to override this interceptor, be sure to call it after your > >> + * own interceptor function has finished. It would generally be a bad idea > >> + * though to override these functions. > >> + * > >> + * @see eo_del_intercept_set() > >> + */ > >> +EAPI Eo_Del_Intercept eo_del_intercept_get(const Eo *obj); > >> + > >> +/** > >> * @brief Unrefs the object and reparents it to NULL. > >> * @param obj the object to work on. > >> * > >> diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c > >> index 996b961..ba12fbd 100644 > >> --- a/src/lib/eo/eo.c > >> +++ b/src/lib/eo/eo.c > >> @@ -1332,6 +1332,22 @@ eo_ref_get(const Eo *obj_id) > >> return obj->refcount; > >> } > >> > >> +EAPI void > >> +eo_del_intercept_set(Eo *obj_id, Eo_Del_Intercept del_intercept_func) > >> +{ > >> + EO_OBJ_POINTER_RETURN(obj_id, obj); > >> + > >> + obj->del_intercept = del_intercept_func; > >> +} > >> + > >> +EAPI Eo_Del_Intercept > >> +eo_del_intercept_get(const Eo *obj_id) > >> +{ > >> + EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL); > >> + > >> + return obj->del_intercept; > >> +} > >> + > >> void > >> _eo_condtor_done(Eo *obj_id) > >> { > >> diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h > >> index 3ee4134..323fc02 100644 > >> --- a/src/lib/eo/eo_private.h > >> +++ b/src/lib/eo/eo_private.h > >> @@ -95,6 +95,7 @@ struct _Eo_Object > >> #endif > >> > >> Eina_List *composite_objects; > >> + Eo_Del_Intercept del_intercept; > >> > >> int refcount; > >> int datarefcount; > >> @@ -295,6 +296,14 @@ _eo_unref(_Eo_Object *obj) > >> ERR("Object %p deletion already triggered. You wrongly > >> call eo_unref() within a destructor.", _eo_id_get(obj)); return; > >> } > >> + > >> + if (obj->del_intercept) > >> + { > >> + (obj->refcount)++; > >> + obj->del_intercept(_eo_id_get(obj)); > >> + return; > >> + } > >> + > >> obj->del_triggered = EINA_TRUE; > >> > >> _eo_del_internal(__FILE__, __LINE__, obj); > >> diff --git a/src/tests/eo/suite/eo_test_general.c > >> b/src/tests/eo/suite/eo_test_general.c index 9a0db0f..2960902 100644 > >> --- a/src/tests/eo/suite/eo_test_general.c > >> +++ b/src/tests/eo/suite/eo_test_general.c > >> @@ -950,6 +950,60 @@ START_TEST(eo_add_failures) > >> } > >> END_TEST > >> > >> +static Eina_Bool intercepted = EINA_FALSE; > >> + > >> +static void > >> +_del_intercept(Eo *obj) > >> +{ > >> + intercepted = EINA_TRUE; > >> + eo_del_intercept_set(obj, NULL); > >> + eo_unref(obj); > >> +} > >> + > >> +START_TEST(eo_del_intercept) > >> +{ > >> +#ifdef HAVE_EO_ID > >> + eo_init(); > >> + > >> + static const Eo_Class_Description class_desc = { > >> + EO_VERSION, > >> + "Simple", > >> + EO_CLASS_TYPE_REGULAR, > >> + EO_CLASS_DESCRIPTION_NOOPS(), > >> + NULL, > >> + 0, > >> + NULL, > >> + NULL > >> + }; > >> + > >> + const Eo_Class *klass = eo_class_new(&class_desc, EO_CLASS, NULL); > >> + fail_if(!klass); > >> + > >> + /* Check unref interception */ > >> + intercepted = EINA_FALSE; > >> + Eo *obj = eo_add(klass, NULL); > >> + fail_if(!obj); > >> + fail_if(!eo_isa(obj, klass)); > >> + eo_del_intercept_set(obj, _del_intercept); > >> + eo_unref(obj); > >> + fail_if(!intercepted); > >> + fail_if(eo_isa(obj, klass)); > >> + > >> + /* Check del interception */ > >> + intercepted = EINA_FALSE; > >> + obj = eo_add(klass, NULL); > >> + fail_if(!obj); > >> + fail_if(!eo_isa(obj, klass)); > >> + eo_del_intercept_set(obj, _del_intercept); > >> + eo_del(obj); > >> + fail_if(!intercepted); > >> + fail_if(eo_isa(obj, klass)); > >> + > >> + eo_shutdown(); > >> +#endif > >> +} > >> +END_TEST > >> + > >> void eo_test_general(TCase *tc) > >> { > >> tcase_add_test(tc, eo_simple); > >> @@ -967,4 +1021,5 @@ void eo_test_general(TCase *tc) > >> tcase_add_test(tc, eo_add_do_and_custom); > >> tcase_add_test(tc, eo_pointers_indirection); > >> tcase_add_test(tc, eo_add_failures); > >> + tcase_add_test(tc, eo_del_intercept); > >> } > >> > > > > > > ------------------------------------------------------------------------------ > > Transform Data into Opportunity. > > Accelerate data analysis in your applications with > > Intel Data Analytics Acceleration Library. > > Click to learn more. > > http://makebettercode.com/inteldaal-eval > > _______________________________________________ > > enlightenment-devel mailing list > > enlightenment-devel@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > > > > > ------------------------------------------------------------------------------ > Transform Data into Opportunity. > Accelerate data analysis in your applications with > Intel Data Analytics Acceleration Library. > Click to learn more. > http://pubads.g.doubleclick.net/gampad/clk?id=278785111&iu=/4140 > _______________________________________________ > enlightenment-devel mailing list > enlightenment-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > -- ------------- Codito, ergo sum - "I code, therefore I am" -------------- The Rasterman (Carsten Haitzler) ras...@rasterman.com ------------------------------------------------------------------------------ Transform Data into Opportunity. Accelerate data analysis in your applications with Intel Data Analytics Acceleration Library. Click to learn more. http://pubads.g.doubleclick.net/gampad/clk?id=278785111&iu=/4140 _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel