Enlightenment CVS committal Author : dj2 Project : e17 Module : libs/ewl
Dir : e17/libs/ewl/src/lib Modified Files: ewl_callback.c ewl_callback.h ewl_enums.h ewl_widget.c ewl_widget.h Log Message: - convert the ewl_callbacks to use an array for their storage instead of an ecore_list. The ecore_list is too heavyweight for what we need in the callbacks. Running Ewl_Test and opening all test windows With ecore_list 9121 dsinclai 15 0 71156 17m 4276 S 0.0 1.8 0:11.06 ewl_test With array 21727 dsinclai 15 0 68360 15m 4304 S 0.0 1.5 0:09.73 ewl_test Running the ewl_filedialog on a directory with 3000 entries With ecore_list 25626 dsinclai 16 0 147m 95m 4084 S 0.0 9.5 0:05.42 ewl_test With array 6871 dsinclai 25 0 115m 63m 4104 S 0.0 6.4 0:04.62 ewl_test =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ewl/src/lib/ewl_callback.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -3 -r1.3 -r1.4 --- ewl_callback.c 5 Sep 2005 14:12:15 -0000 1.3 +++ ewl_callback.c 16 Sep 2005 19:00:24 -0000 1.4 @@ -8,8 +8,13 @@ static Ewl_Callback *ewl_callback_register(Ewl_Callback * cb); static void ewl_callback_unregister(Ewl_Callback * cb); +static void ewl_callback_rm(Ewl_Widget *w, Ewl_Callback_Type t, + unsigned int pos); +static int ewl_callback_insert(Ewl_Widget *w, Ewl_Callback_Type t, + Ewl_Callback *cb, unsigned int pos); + static int callback_id = 0; -static Ecore_Hash *cb_registration = NULL; +static Ecore_Hash *cb_registration = NULL; /** * @return Returns no value. @@ -24,6 +29,15 @@ * 15901 ningerso 10 0 20120 19M 9148 S 0.0 7.0 0:34 ewl_test * * So using shared callbacks saves us over 2 MB of memory in this case. + * + * + * Ecore_list as the callback storage with all tests open has a top line of: + * 9121 dsinclai 15 0 71156 17m 4276 S 0.0 1.8 0:11.06 ewl_test + * Using an array as the callback storage with all tests open has a top line of: + * 21727 dsinclai 15 0 68360 15m 4304 S 0.0 1.5 0:09.73 ewl_test + * + * So using an array for the callbacks saves us about 2MB of memory in this + * case. */ void ewl_callbacks_init() { @@ -57,7 +71,6 @@ Ewl_Callback *found; DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR_RET("cb", cb, NULL); found = ecore_hash_get(cb_registration, cb); @@ -83,7 +96,6 @@ static void ewl_callback_unregister(Ewl_Callback * cb) { DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR("cb", cb); cb->references--; @@ -95,6 +107,106 @@ DLEAVE_FUNCTION(DLEVEL_STABLE); } +static void +ewl_callback_rm(Ewl_Widget *w, Ewl_Callback_Type t, unsigned int pos) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR("w", w); + + /* deal with the direct case first */ + if (w->callbacks[t].mask & EWL_CALLBACK_TYPE_DIRECT) + { + ewl_callback_unregister((Ewl_Callback *)w->callbacks[t].list); + + w->callbacks[t].len = 0; + w->callbacks[t].list = NULL; + EWL_CALLBACK_SET_NODIRECT(w, t); + + DRETURN(DLEVEL_STABLE); + } + ewl_callback_unregister(w->callbacks[t].list[pos]); + + /* if this will empty the list (we've already handled direct) */ + if ((EWL_CALLBACK_LEN(w, t) - 1) == 0) + { + w->callbacks[t].len = 0; + w->callbacks[t].list[0] = NULL; + FREE(w->callbacks[t].list); + + DRETURN(DLEVEL_STABLE); + } + + /* not the last position */ + if (pos != (EWL_CALLBACK_LEN(w, t) - 1)) + { + memmove(w->callbacks[t].list + pos, + w->callbacks[t].list + (pos + 1), + (w->callbacks[t].len - pos - 1) * sizeof(void *)); + } + + w->callbacks[t].len -= 1; + w->callbacks[t].list[EWL_CALLBACK_LEN(w, t)] = NULL; + w->callbacks[t].list = realloc(w->callbacks[t].list, + w->callbacks[t].len * sizeof(void *)); + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + +static int +ewl_callback_insert(Ewl_Widget *w, Ewl_Callback_Type t, + Ewl_Callback *cb, unsigned int pos) +{ + Ewl_Callback *old = NULL; + + DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("w", w, 0); + DCHECK_PARAM_PTR_RET("cb", cb, 0); + + /* set direct if possible */ + if (!EWL_CALLBACK_LEN(w, t)) + { + w->callbacks[t].list = (void *)cb; + w->callbacks[t].len = 1; + EWL_CALLBACK_SET_DIRECT(w, t); + + DRETURN_INT(cb->id, DLEVEL_STABLE); + } + w->callbacks[t].len ++; + + /* if we have a type direct then we need to save off the direct + * pointer and set the list to NULL so it'll be allocd' correctly */ + if (w->callbacks[t].mask & EWL_CALLBACK_TYPE_DIRECT) + { + old = (Ewl_Callback *)w->callbacks[t].list; + w->callbacks[t].list = NULL; + EWL_CALLBACK_SET_NODIRECT(w, t); + } + + w->callbacks[t].list = realloc(w->callbacks[t].list, + w->callbacks[t].len * sizeof(void *)); + + /* if old is set this was a direct so we can just set 0, 1 and be + * done with it */ + if (old) + { + w->callbacks[t].list[0] = (!pos ? cb : old); + w->callbacks[t].list[1] = ( pos ? cb : old); + } + else + { + /* only have to move if we aren't at the end (of the + * original lenth already */ + if (pos != (w->callbacks[t].len - 1)) + { + memmove(w->callbacks[t].list + (pos + 1), + w->callbacks[t].list + pos, + (w->callbacks[t].len - 1) * sizeof(void *)); + } + w->callbacks[t].list[pos] = cb; + } + DRETURN_INT(cb->id, DLEVEL_STABLE); +} + /** * @param w: the widget to attach the callback * @param t: the type of the callback that is being attached @@ -112,11 +224,11 @@ Ewl_Callback_Function f, void *user_data) { Ewl_Callback *cb; - Ecore_List *list; + int ret; DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR_RET("w", w, -1); - DCHECK_PARAM_PTR_RET("f", f, -1); + DCHECK_PARAM_PTR_RET("w", w, 0); + DCHECK_PARAM_PTR_RET("f", f, 0); cb = NEW(Ewl_Callback, 1); if (!cb) @@ -126,17 +238,9 @@ cb->user_data = user_data; cb = ewl_callback_register(cb); + ret = ewl_callback_insert(w, t, cb, EWL_CALLBACK_LEN(w, t)); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list) { - list = ecore_list_new(); - EWL_CALLBACK_LIST_ASSIGN(w, t, list); - } - - ecore_list_append(list, cb); - - DRETURN_INT(cb->id, DLEVEL_STABLE); + DRETURN_INT(ret, DLEVEL_STABLE); } /** @@ -154,12 +258,12 @@ ewl_callback_prepend(Ewl_Widget * w, Ewl_Callback_Type t, Ewl_Callback_Function f, void *user_data) { - Ewl_Callback *cb; - Ecore_List *list; + Ewl_Callback *cb; + int ret; DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR_RET("w", w, -1); - DCHECK_PARAM_PTR_RET("f", f, -1); + DCHECK_PARAM_PTR_RET("w", w, 0); + DCHECK_PARAM_PTR_RET("f", f, 0); cb = NEW(Ewl_Callback, 1); if (!cb) @@ -169,17 +273,9 @@ cb->user_data = user_data; cb = ewl_callback_register(cb); + ret = ewl_callback_insert(w, t, cb, 0); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list) { - list = ecore_list_new(); - EWL_CALLBACK_LIST_ASSIGN(w, t, list); - } - - ecore_list_prepend(list, cb); - - DRETURN_INT(cb->id, DLEVEL_STABLE); + DRETURN_INT(ret, DLEVEL_STABLE); } /** @@ -202,7 +298,7 @@ { Ewl_Callback *cb; Ewl_Callback *search; - Ecore_List *list; + int ret, pos = 0; DENTER_FUNCTION(DLEVEL_STABLE); @@ -218,23 +314,21 @@ cb = ewl_callback_register(cb); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list) { - list = ecore_list_new(); - EWL_CALLBACK_LIST_ASSIGN(w, t, list); - } - /* * Step 1 position past the callback we want to insert after. */ - ecore_list_goto_first(list); - while ((search = ecore_list_next(list)) && - (search->func != after || search->user_data != after_data)); - - ecore_list_insert(list, cb); + for (pos = 0; pos < EWL_CALLBACK_LEN(w, t); pos++) + { + search = EWL_CALLBACK_GET(w, t, pos); + if ((search->func == after) && (search->user_data == after_data)) + { + pos ++; + break; + } + } + ret = ewl_callback_insert(w, t, cb, pos); - DRETURN_INT(cb->id, DLEVEL_STABLE); + DRETURN_INT(ret, DLEVEL_STABLE); } /** @@ -268,9 +362,9 @@ ewl_callback_call_with_event_data(Ewl_Widget * w, Ewl_Callback_Type t, void *ev_data) { - Ecore_List *list; Ewl_Callback *cb; Ewl_Widget *parent, *top = NULL; + int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); @@ -304,19 +398,18 @@ ewl_callback_call_with_event_data(top, t, ev_data); /* - * Finally execute the callback on the current widget + * Make sure the widget has callbacks of the given type */ - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list || ecore_list_is_empty(list)) + if (!EWL_CALLBACK_LEN(w, t)) DRETURN(DLEVEL_STABLE); /* * Loop through and execute each of the callbacks of a certain type for * the specified widget. */ - ecore_list_goto_first(list); - while (list && (cb = ecore_list_next(list))) { + for (i = 0; i < EWL_CALLBACK_LEN(w, t); i++) + { + cb = EWL_CALLBACK_GET(w, t, i); if (cb->func) cb->func(w, ev_data, cb->user_data); } @@ -334,22 +427,14 @@ */ void ewl_callback_del_type(Ewl_Widget * w, Ewl_Callback_Type t) { - Ecore_List *list; - Ewl_Callback *rm; - DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list) + if (!EWL_CALLBACK_LEN(w, t)) DRETURN(DLEVEL_STABLE); - while ((rm = ecore_list_remove_first(list))) - ewl_callback_unregister(rm); - - ecore_list_destroy(list); - EWL_CALLBACK_LIST_ASSIGN(w, t, NULL); + while (EWL_CALLBACK_LEN(w, t)) + ewl_callback_rm(w, t, EWL_CALLBACK_LEN(w, t) - 1); DLEAVE_FUNCTION(DLEVEL_STABLE); } @@ -365,22 +450,20 @@ */ void ewl_callback_del_cb_id(Ewl_Widget * w, Ewl_Callback_Type t, int cb_id) { - Ecore_List *list; Ewl_Callback *cb; + int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list || - ecore_list_is_empty(list) || cb_id > callback_id) + if (!EWL_CALLBACK_LEN(w, t) || cb_id > callback_id) DRETURN(DLEVEL_STABLE); - while ((cb = ecore_list_next(list))) { + for (i = 0; i < EWL_CALLBACK_LEN(w, t); i++) + { + cb = EWL_CALLBACK_GET(w, t, i); if (cb->id == cb_id) { - ecore_list_remove(list); - ewl_callback_unregister(cb); + ewl_callback_rm(w, t, i); break; } } @@ -403,11 +486,8 @@ DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); - for (i = 0; i < EWL_CALLBACK_MAX; i++) { - if (EWL_CALLBACK_LIST_POINTER(w, i)) - ewl_callback_del_type(w, i); - } - + for (i = 0; i < EWL_CALLBACK_MAX; i++) + ewl_callback_del_type(w, i); DLEAVE_FUNCTION(DLEVEL_STABLE); } @@ -426,26 +506,21 @@ ewl_callback_del(Ewl_Widget * w, Ewl_Callback_Type t, Ewl_Callback_Function f) { Ewl_Callback *cb; - Ecore_List *list; + int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list || ecore_list_is_empty(list)) + if (!EWL_CALLBACK_LEN(w, t)) DRETURN(DLEVEL_STABLE); - ecore_list_goto_first(list); - - while ((cb = ecore_list_current(list)) != NULL) { + for (i = 0; i < EWL_CALLBACK_LEN(w, t); i++) + { + cb = EWL_CALLBACK_GET(w, t, i); if (cb->func == f) { - ecore_list_remove(list); - ewl_callback_unregister(cb); + ewl_callback_rm(w, t, i); break; } - - ecore_list_next(list); } DLEAVE_FUNCTION(DLEVEL_STABLE); @@ -467,26 +542,21 @@ Ewl_Callback_Function f, void *d) { Ewl_Callback *cb; - Ecore_List *list; + int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); - list = EWL_CALLBACK_LIST_POINTER(w, t); - - if (!list || ecore_list_is_empty(list)) + if (!EWL_CALLBACK_LEN(w, t)) DRETURN(DLEVEL_STABLE); - ecore_list_goto_first(list); - - while ((cb = ecore_list_current(list)) != NULL) { - if (cb->func == f && cb->user_data == d) { - ecore_list_remove(list); - ewl_callback_unregister(cb); + for (i = 0; i < EWL_CALLBACK_LEN(w, t); i++) + { + cb = EWL_CALLBACK_GET(w, t, i); + if ((cb->func == f) && (cb->user_data == d)) { + ewl_callback_rm(w, t, i); break; } - - ecore_list_next(list); } DLEAVE_FUNCTION(DLEVEL_STABLE); @@ -497,12 +567,13 @@ */ static unsigned int ewl_callback_hash(void *key) { - Ewl_Callback *cb = EWL_CALLBACK(key); + Ewl_Callback *cb; DENTER_FUNCTION(DLEVEL_STABLE); - DCHECK_PARAM_PTR_RET("key", key, 0); + cb = EWL_CALLBACK(key); + DRETURN_INT((unsigned int) (cb->func) ^ (unsigned int) (cb->user_data), DLEVEL_STABLE); } @@ -513,15 +584,19 @@ */ static int ewl_callback_compare(void *key1, void *key2) { - Ewl_Callback *cb1 = EWL_CALLBACK(key1); - Ewl_Callback *cb2 = EWL_CALLBACK(key2); + Ewl_Callback *cb1; + Ewl_Callback *cb2; DENTER_FUNCTION(DLEVEL_STABLE); + DCHECK_PARAM_PTR_RET("key1", key1, -1); + DCHECK_PARAM_PTR_RET("key2", key2, -1); - DCHECK_PARAM_PTR_RET("key1", key1, -1) - DCHECK_PARAM_PTR_RET("key2", key2, -1) - if (cb1->func == cb2->func && cb1->user_data == cb2->user_data) + cb1 = EWL_CALLBACK(key1); + cb2 = EWL_CALLBACK(key2); + + if ((cb1->func == cb2->func) && (cb1->user_data == cb2->user_data)) DRETURN_INT(0, DLEVEL_STABLE); DRETURN_INT(-1, DLEVEL_STABLE); } + =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ewl/src/lib/ewl_callback.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -3 -r1.3 -r1.4 --- ewl_callback.h 10 Apr 2005 05:24:09 -0000 1.3 +++ ewl_callback.h 16 Sep 2005 19:00:24 -0000 1.4 @@ -48,16 +48,30 @@ #define EWL_CALLBACK_NOTIFY_MASK (0x3) /** - * @def EWL_CALLBACK_LIST_POINTER(w, t) + * @def EWL_CALLBACK_LIST(w, t) * Retrives the callback list from a widget for a certain event type. */ -#define EWL_CALLBACK_LIST_POINTER(w, t) (w->callbacks[t].list) +#define EWL_CALLBACK_LIST(w, t) (w->callbacks[t].list) /** * @def EWL_CALLBACK_FLAGS(w, t) * Retrives the callback flags from a widget for a certain event type. */ #define EWL_CALLBACK_FLAGS(w, t) (w->callbacks[t].mask) + +/** + * @def EWL_CALLBACK_LEN(w, t) + * Retrives the length from a widget for a certain event type. + */ +#define EWL_CALLBACK_LEN(w, t) (w->callbacks[t].len) + +/** + * @def EWL_CALLBACK_GET(w, t, i) + * Retrives the callback struct at the given position + */ +#define EWL_CALLBACK_GET(w, t, i) \ + ((w->callbacks[t].mask & EWL_CALLBACK_TYPE_DIRECT) ? w->callbacks[t].list : w->callbacks[t].list[i]) + /** * @def EWL_CALLBACK_FLAG_INTERCEPT(w, t) * Sets the callback intercept flag from a widget for a certain event type. @@ -80,11 +94,19 @@ w->callbacks[t].mask |= EWL_CALLBACK_NOTIFY_NOTIFY /** - * @def EWL_CALLBACK_LIST_ASSIGN(w, t, l) - * Sets the callback list for a widget for a certain event type. + * @def EWL_CALLBACK_SET_DIRECT(w, t) + * Sets the callback direct flag for a centain event type */ -#define EWL_CALLBACK_LIST_ASSIGN(w, t, l) \ - w->callbacks[t].list = l +#define EWL_CALLBACK_SET_DIRECT(w, t) \ + w->callbacks[t].mask |= EWL_CALLBACK_TYPE_DIRECT + +/** + * @def EWL_CALLBACK_SET_NODIRECT(w, t) + * Clears the callback direct flag from a widget for a certain event type + */ +#define EWL_CALLBACK_SET_NODIRECT(w, t) \ + w->callbacks[t].mask &= ~EWL_CALLBACK_TYPE_DIRECT + void ewl_callbacks_init(void); void ewl_callbacks_shutdown(void); =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ewl/src/lib/ewl_enums.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -3 -r1.6 -r1.7 --- ewl_enums.h 21 Jul 2005 00:47:58 -0000 1.6 +++ ewl_enums.h 16 Sep 2005 19:00:24 -0000 1.7 @@ -58,7 +58,9 @@ { EWL_CALLBACK_NOTIFY_NONE = 0, EWL_CALLBACK_NOTIFY_NOTIFY = 1, - EWL_CALLBACK_NOTIFY_INTERCEPT = 2 + EWL_CALLBACK_NOTIFY_INTERCEPT = 2, + + EWL_CALLBACK_TYPE_DIRECT = 4 }; typedef enum Ewl_Event_Notify Ewl_Event_Notify; =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ewl/src/lib/ewl_widget.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -3 -r1.14 -r1.15 --- ewl_widget.c 5 Sep 2005 14:12:15 -0000 1.14 +++ ewl_widget.c 16 Sep 2005 19:00:24 -0000 1.15 @@ -1041,7 +1041,7 @@ void ewl_widget_destroy_cb(Ewl_Widget * w, void *ev_data __UNUSED__, void *data __UNUSED__) { - Ecore_List *destroy_cbs; + int i; DENTER_FUNCTION(DLEVEL_STABLE); DCHECK_PARAM_PTR("w", w); @@ -1071,14 +1071,14 @@ /* * Clear out the callbacks, this is a bit tricky because we don't want * to continue using this widget after the callbacks have been - * deleted. So we remove the callbacks of type destroy and then clear - * the remaining callbacks. This preserves the list of the destroy - * type so we don't get a segfault. - */ - destroy_cbs = EWL_CALLBACK_LIST_POINTER(w, EWL_CALLBACK_DESTROY); - EWL_CALLBACK_LIST_ASSIGN(w, EWL_CALLBACK_DESTROY, NULL); - ewl_callback_clear(w); - EWL_CALLBACK_LIST_ASSIGN(w, EWL_CALLBACK_DESTROY, destroy_cbs); + * deleted. Clear all callbacks except for the destroy callbacks. + * This preserves the list of the destroy type so we don't get a segfault. + */ + for (i = 0; i < EWL_CALLBACK_MAX; i++) + { + if (i == EWL_CALLBACK_DESTROY) continue; + ewl_callback_del_type(w, i); + } DLEAVE_FUNCTION(DLEVEL_STABLE); } =================================================================== RCS file: /cvsroot/enlightenment/e17/libs/ewl/src/lib/ewl_widget.h,v retrieving revision 1.10 retrieving revision 1.11 diff -u -3 -r1.10 -r1.11 --- ewl_widget.h 22 Jul 2005 00:03:04 -0000 1.10 +++ ewl_widget.h 16 Sep 2005 19:00:24 -0000 1.11 @@ -21,8 +21,9 @@ struct Ewl_Callback_Chain { - Ecore_List *list; - unsigned int mask; + void **list; + unsigned short mask; + unsigned short len; }; typedef struct Ewl_Color_Set Ewl_Color_Set; ------------------------------------------------------- SF.Net email is sponsored by: Tame your development challenges with Apache's Geronimo App Server. Download it for free - -and be entered to win a 42" plasma tv or your very own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs