From 3ec36334a4f1864db192273179603acf195a13f1 Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 15 May 2012 14:17:03 +0000 Subject: [PATCH] Eo: Added support for event freeze/thaw. SVN revision: 71120 --- legacy/eobj/examples/signals/main.c | 106 ++++++++++++++++++++++++++++ legacy/eobj/lib/Eo.h | 75 ++++++++++++++++++++ legacy/eobj/lib/eo_base_class.c | 76 ++++++++++++++++++++ 3 files changed, 257 insertions(+) diff --git a/legacy/eobj/examples/signals/main.c b/legacy/eobj/examples/signals/main.c index 7ceb52382d..7636fc8c7a 100644 --- a/legacy/eobj/examples/signals/main.c +++ b/legacy/eobj/examples/signals/main.c @@ -67,6 +67,112 @@ main(int argc, char *argv[]) fail_if(ret); fail_if(pd->cb_count != 0); + + /* Freeze/thaw. */ + int fcount = 0; + cb_count = 0; + eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 1)); + fail_if(pd->cb_count != 1); + + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_do(obj, eo_event_freeze()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_do(obj, eo_event_freeze()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 2); + + eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 2)); + fail_if(pd->cb_count != 1); + + eo_do(obj, simple_a_set(2)); + fail_if(cb_count != 0); + eo_do(obj, eo_event_thaw()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_do(obj, eo_event_thaw()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_do(obj, simple_a_set(3)); + fail_if(cb_count != 2); + + cb_count = 0; + eo_do(obj, eo_event_thaw()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_do(obj, eo_event_freeze()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_do(obj, simple_a_set(2)); + fail_if(cb_count != 0); + eo_do(obj, eo_event_thaw()); + eo_do(obj, eo_event_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret)); + fail_if(!ret); + eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret)); + fail_if(!ret); + eo_do(obj, eo_event_callback_del_lazy(EV_A_CHANGED, _a_changed_cb, &ret)); + fail_if(ret); + + /* Global Freeze/thaw. */ + fcount = 0; + cb_count = 0; + pd->cb_count = 0; + eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 1)); + fail_if(pd->cb_count != 1); + + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 2); + + eo_do(obj, eo_event_callback_priority_add(EV_A_CHANGED, EO_CALLBACK_PRIORITY_BEFORE, _a_changed_cb, (void *) 2)); + fail_if(pd->cb_count != 1); + + eo_do(obj, simple_a_set(2)); + fail_if(cb_count != 0); + eo_class_do(EO_BASE_CLASS, eo_event_global_thaw()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_class_do(EO_BASE_CLASS, eo_event_global_thaw()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_do(obj, simple_a_set(3)); + fail_if(cb_count != 2); + + cb_count = 0; + eo_class_do(EO_BASE_CLASS, eo_event_global_thaw()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 1); + + eo_do(obj, simple_a_set(2)); + fail_if(cb_count != 0); + eo_class_do(EO_BASE_CLASS, eo_event_global_thaw()); + eo_class_do(EO_BASE_CLASS, eo_event_global_freeze_get(&fcount)); + fail_if(fcount != 0); + + eo_unref(obj); eo_shutdown(); return 0; diff --git a/legacy/eobj/lib/Eo.h b/legacy/eobj/lib/Eo.h index 1e41674060..36ca914d2b 100644 --- a/legacy/eobj/lib/Eo.h +++ b/legacy/eobj/lib/Eo.h @@ -791,6 +791,12 @@ enum { EO_BASE_SUB_ID_EVENT_CALLBACK_CALL, EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD, EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL, + EO_BASE_SUB_ID_EVENT_FREEZE, + EO_BASE_SUB_ID_EVENT_THAW, + EO_BASE_SUB_ID_EVENT_FREEZE_GET, + EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE, + EO_BASE_SUB_ID_EVENT_GLOBAL_THAW, + EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE_GET, EO_BASE_SUB_ID_LAST }; @@ -952,6 +958,75 @@ typedef Eina_Bool (*Eo_Event_Cb)(void *data, Eo *obj, const Eo_Event_Description */ #define eo_event_callback_forwarder_del(desc, new_obj) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL), EO_TYPECHECK(const Eo_Event_Description *, desc), EO_TYPECHECK(Eo *, new_obj) +/** + * @def eo_event_freeze + * @brief freeze events of object. + * + * Prevents event callbacks from being called for the object. + * + * @see #eo_event_thaw + */ +#define eo_event_freeze() EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE) + +/** + * @def eo_event_thaw + * @brief thaw events of object. + * + * Lets event callbacks be called for the object. + * + * @see #eo_event_freeze + */ +#define eo_event_thaw() EO_BASE_ID(EO_BASE_SUB_ID_EVENT_THAW) + +/** + * @def eo_event_freeze_get + * @brief return freeze events of object. + * + * @param fcount[out] The event freeze count of the object. + * + * Return event freeze count. + * + * @see #eo_event_freeze + * @see #eo_event_thaw + */ +#define eo_event_freeze_get(fcount) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE_GET), EO_TYPECHECK(int *, fcount) + +/** + * @def eo_event_global_freeze + * @brief freeze events of object. + * + * Prevents event callbacks from being called for the object. + * + * @see #eo_event_freeze + * @see #eo_event_global_thaw + */ +#define eo_event_global_freeze() EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE) + +/** + * @def eo_event_global_thaw + * @brief thaw events of object. + * + * Lets event callbacks be called for the object. + * + * @see #eo_event_thaw + * @see #eo_event_global_freeze + */ +#define eo_event_global_thaw() EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_THAW) + +/** + * @def eo_event_global_freeze_get + * @brief return freeze events of object. + * + * @param fcount[out] The event freeze count of the object. + * + * Return event freeze count. + * + * @see #eo_event_freeze_get + * @see #eo_event_global_freeze + * @see #eo_event_global_thaw + */ +#define eo_event_global_freeze_get(fcount) EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE_GET), EO_TYPECHECK(int *, fcount) + /** * @def eo_event_callback_add(obj, desc, cb, data) * Add a callback for an event. diff --git a/legacy/eobj/lib/eo_base_class.c b/legacy/eobj/lib/eo_base_class.c index c0e24d62ee..5de6b3a2a3 100644 --- a/legacy/eobj/lib/eo_base_class.c +++ b/legacy/eobj/lib/eo_base_class.c @@ -7,6 +7,8 @@ EAPI Eo_Op EO_BASE_BASE_ID = EO_NOOP; +static int event_freeze_count = 0; + typedef struct { Eina_Inlist *generic_data; @@ -14,6 +16,7 @@ typedef struct Eina_Inlist *callbacks; int walking_list; + int event_freeze_count; } Private_Data; typedef struct @@ -373,6 +376,9 @@ _ev_cb_call(const Eo *_obj, const void *class_data, va_list *list) if (ret) *ret = EINA_TRUE; + if (event_freeze_count || pd->event_freeze_count) + return; + /* FIXME: Change eo_ref to _eo_ref and unref. */ eo_ref(obj); pd->walking_list++; @@ -426,6 +432,62 @@ _ev_cb_forwarder_del(Eo *obj, void *class_data EINA_UNUSED, va_list *list) eo_do(obj, eo_event_callback_del(desc, _eo_event_forwarder_callback, new_obj)); } +static void +_ev_freeze(Eo *obj EINA_UNUSED, void *class_data, va_list *list EINA_UNUSED) +{ + Private_Data *pd = (Private_Data *) class_data; + pd->event_freeze_count++; +} + +static void +_ev_thaw(Eo *obj, void *class_data, va_list *list EINA_UNUSED) +{ + Private_Data *pd = (Private_Data *) class_data; + if (pd->event_freeze_count > 0) + { + pd->event_freeze_count--; + } + else + { + ERR("Events for object %p have already been thawed.", obj); + } +} + +static void +_ev_freeze_get(const Eo *obj EINA_UNUSED, const void *class_data, va_list *list) +{ + Private_Data *pd = (Private_Data *) class_data; + int *ret = va_arg(*list, int *); + *ret = pd->event_freeze_count; +} + +static void +_ev_global_freeze(const Eo_Class *klass EINA_UNUSED, va_list *list EINA_UNUSED) +{ + event_freeze_count++; +} + +static void +_ev_global_thaw(const Eo_Class *klass EINA_UNUSED, va_list *list EINA_UNUSED) +{ + if (event_freeze_count > 0) + { + event_freeze_count--; + } + else + { + ERR("Global events have already been thawed."); + } +} + +static void +_ev_global_freeze_get(const Eo_Class *klass EINA_UNUSED, va_list *list) +{ + int *ret = va_arg(*list, int *); + *ret = event_freeze_count; +} + + /* EOF event callbacks */ @@ -459,6 +521,8 @@ _destructor(Eo *obj, void *class_data) static void _class_constructor(Eo_Class *klass) { + event_freeze_count = 0; + const Eo_Op_Func_Description func_desc[] = { EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DATA_SET), _data_set), EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_DATA_GET), _data_get), @@ -471,6 +535,12 @@ _class_constructor(Eo_Class *klass) EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL), _ev_cb_call), EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD), _ev_cb_forwarder_add), EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL), _ev_cb_forwarder_del), + EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE), _ev_freeze), + EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_THAW), _ev_thaw), + EO_OP_FUNC_CONST(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE_GET), _ev_freeze_get), + EO_OP_FUNC_CLASS(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE), _ev_global_freeze), + EO_OP_FUNC_CLASS(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_THAW), _ev_global_thaw), + EO_OP_FUNC_CLASS(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE_GET), _ev_global_freeze_get), EO_OP_FUNC_SENTINEL }; @@ -489,6 +559,12 @@ static const Eo_Op_Description op_desc[] = { EO_OP_DESCRIPTION_CONST(EO_BASE_SUB_ID_EVENT_CALLBACK_CALL, "?", "Call the event callbacks for an event."), EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_ADD, "?", "Add an event forwarder."), EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_CALLBACK_FORWARDER_DEL, "?", "Delete an event forwarder."), + EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_FREEZE, "?", "Freezes events."), + EO_OP_DESCRIPTION(EO_BASE_SUB_ID_EVENT_THAW, "?", "Thaws events."), + EO_OP_DESCRIPTION_CONST(EO_BASE_SUB_ID_EVENT_FREEZE_GET, "?", "Get event freeze counter."), + EO_OP_DESCRIPTION_CLASS(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE, "?", "Freezes events globally."), + EO_OP_DESCRIPTION_CLASS(EO_BASE_SUB_ID_EVENT_GLOBAL_THAW, "?", "Thaws events globally."), + EO_OP_DESCRIPTION_CLASS(EO_BASE_SUB_ID_EVENT_GLOBAL_FREEZE_GET, "?", "Get global event freeze counter."), EO_OP_DESCRIPTION_SENTINEL };