Enlightenment CVS committal Author : ningerso Project : e17 Module : libs/ewl
Dir : e17/libs/ewl/src/lib Modified Files: ewl_misc.c Log Message: Use a buffered queue to reduce memory management overhead when queueing widgets for the configure loop. This should also reduce memory fragmentation. =================================================================== RCS file: /cvs/e/e17/libs/ewl/src/lib/ewl_misc.c,v retrieving revision 1.86 retrieving revision 1.87 diff -u -3 -r1.86 -r1.87 --- ewl_misc.c 5 Mar 2007 11:52:54 -0000 1.86 +++ ewl_misc.c 5 Mar 2007 14:12:58 -0000 1.87 @@ -31,12 +31,33 @@ */ static Ecore_List *obscure_list = NULL; static Ecore_List *reveal_list = NULL; -static Ecore_List *configure_list = NULL; static Ecore_List *realize_list = NULL; static Ecore_List *destroy_list = NULL; static Ecore_List *child_add_list= NULL; /* + * Default size per-buffer in the configure queue management. + */ +#define EWL_CONFIGURE_QUEUE_SIZE 4092 + +/* + * Memory buffer for tracking widgets ready for a configure pass + */ +typedef struct Ewl_Configure_Queue Ewl_Configure_Queue; +struct Ewl_Configure_Queue +{ + int end; + Ewl_Widget *buffer[EWL_CONFIGURE_QUEUE_SIZE]; +}; + +/* + * Lists of active and inactive buffers + * FIXME: Need to occassionally reduce the inactive buffer list + */ +Ecore_List *configure_active = NULL; +Ecore_List *configure_available = NULL; + +/* * Lists for cleaning up evas related memory at convenient times. */ static Ecore_List *free_evas_list = NULL; @@ -47,7 +68,7 @@ static int ewl_idle_render(void *data); static void ewl_init_parse_options(int *argc, char **argv); static void ewl_init_remove_option(int *argc, char **argv, int i); -static void ewl_configure_queue(void); +static void ewl_configure_queue_run(void); static void ewl_realize_queue(void); static int ewl_garbage_collect_idler(void *data); static void ewl_configure_cancel_request(Ewl_Widget *w); @@ -170,7 +191,8 @@ reveal_list = ecore_list_new(); obscure_list = ecore_list_new(); - configure_list = ecore_list_new(); + configure_active = ecore_list_new(); + configure_available = ecore_list_new(); realize_list = ecore_list_new(); destroy_list = ecore_list_new(); free_evas_list = ecore_list_new(); @@ -179,7 +201,8 @@ ewl_embed_list = ecore_list_new(); ewl_window_list = ecore_list_new(); shutdown_hooks = ecore_list_new(); - if ((!reveal_list) || (!obscure_list) || (!configure_list) + if ((!reveal_list) || (!obscure_list) || (!configure_active) + || (!configure_available) || (!realize_list) || (!destroy_list) || (!free_evas_list) || (!free_evas_object_list) || (!child_add_list) || (!ewl_embed_list) @@ -189,6 +212,12 @@ goto ERROR; } + /* + * Cleanup the queue buffers when the management lists get freed. + */ + ecore_list_set_free_cb(configure_active, free); + ecore_list_set_free_cb(configure_available, free); + if (!ewl_config_init()) { fprintf(stderr, "Could not initilaize Ewl Config.\n"); goto ERROR; @@ -313,7 +342,8 @@ IF_FREE_LIST(ewl_window_list); IF_FREE_LIST(reveal_list); IF_FREE_LIST(obscure_list); - IF_FREE_LIST(configure_list); + IF_FREE_LIST(configure_active); + IF_FREE_LIST(configure_available); IF_FREE_LIST(realize_list); IF_FREE_LIST(destroy_list); IF_FREE_LIST(free_evas_list); @@ -405,8 +435,8 @@ if (!ecore_list_is_empty(realize_list)) ewl_realize_queue(); - while (!ecore_list_is_empty(configure_list)) { - ewl_configure_queue(); + while (!ecore_list_is_empty(configure_active)) { + ewl_configure_queue_run(); /* * Reclaim obscured objects at this point @@ -689,8 +719,10 @@ void ewl_configure_request(Ewl_Widget * w) { + Ewl_Object *o; Ewl_Embed *emb; Ewl_Widget *search; + Ewl_Configure_Queue *queue_buffer; DENTER_FUNCTION(DLEVEL_TESTING); DCHECK_PARAM_PTR("w", w); @@ -699,22 +731,20 @@ if (!VISIBLE(w)) DRETURN(DLEVEL_STABLE); - /* - * Widget scheduled for destruction - */ - if (ewl_object_queued_has(EWL_OBJECT(w), EWL_FLAG_QUEUED_DSCHEDULED)) - DRETURN(DLEVEL_STABLE); + o = EWL_OBJECT(w); /* - * Widget already scheduled for configure + * Widget scheduled for destruction, configuration, or is being called + * within a configure callback. */ - if (ewl_object_queued_has(EWL_OBJECT(w), EWL_FLAG_QUEUED_CSCHEDULED)) - DRETURN(DLEVEL_STABLE); - /* - * Widget already in configure callback - */ - if (ewl_object_queued_has(EWL_OBJECT(w), EWL_FLAG_QUEUED_CPROCESS)) + if (ewl_object_queued_has(o, EWL_FLAG_QUEUED_DSCHEDULED) || + ewl_object_queued_has(o, EWL_FLAG_QUEUED_CSCHEDULED) || + ewl_object_queued_has(o, EWL_FLAG_QUEUED_CPROCESS)) + */ + if (ewl_object_queued_has(o, EWL_FLAG_QUEUED_DSCHEDULED | + EWL_FLAG_QUEUED_CSCHEDULED | + EWL_FLAG_QUEUED_CPROCESS)) DRETURN(DLEVEL_STABLE); emb = ewl_embed_widget_find(w); @@ -736,61 +766,111 @@ * children widgets should have been removed by this point. */ ewl_object_queued_add(EWL_OBJECT(w), EWL_FLAG_QUEUED_CSCHEDULED); - ecore_list_append(configure_list, w); + + queue_buffer = ecore_list_goto_last(configure_active); + + /* + * If the last buffer is full, it's not useful to us and we need a new + * one. + */ + if (queue_buffer) { + if (queue_buffer->end >= EWL_CONFIGURE_QUEUE_SIZE) + queue_buffer = NULL; + } + + if (!queue_buffer) { + /* + * Attempt to use a previously allocated buffer first, fallback + * to allocating one. + */ + if (!ecore_list_is_empty(configure_available)) { + queue_buffer = ecore_list_remove_first(configure_available); + } + else { + queue_buffer = NEW(Ewl_Configure_Queue, 1); + } + ecore_list_append(configure_active, queue_buffer); + } + + /* + * Add the widget to the end of the queue. + */ + if (queue_buffer) + queue_buffer->buffer[queue_buffer->end++] = w; DLEAVE_FUNCTION(DLEVEL_TESTING); } +static void +ewl_configure_queue_widget_run(Ewl_Widget *w) +{ + DENTER_FUNCTION(DLEVEL_STABLE); + + if (ewl_object_flags_get(EWL_OBJECT(w), + EWL_FLAG_PROPERTY_TOPLEVEL)) { + ewl_object_size_request(EWL_OBJECT(w), + ewl_object_current_w_get(EWL_OBJECT(w)), + ewl_object_current_h_get(EWL_OBJECT(w))); + } + + /* + * Remove the flag that the widget is scheduled for + * configuration. + */ + ewl_object_queued_remove(EWL_OBJECT(w), EWL_FLAG_QUEUED_CSCHEDULED); + + /* + * Items that are off screen should be queued to give up their + * evas objects for reuse. Items returning from offscreen are + * queued to receive new evas objects. + */ + if (!ewl_widget_onscreen_is(w)) { + if (!OBSCURED(w)) + ecore_list_prepend(obscure_list, w); + } + else { + if (OBSCURED(w)) + ecore_list_prepend(reveal_list, w); + + ewl_object_queued_add(EWL_OBJECT(w), EWL_FLAG_QUEUED_CPROCESS); + if (REALIZED(w) && VISIBLE(w) && !OBSCURED(w)) + ewl_callback_call(w, EWL_CALLBACK_CONFIGURE); + ewl_object_queued_remove(EWL_OBJECT(w), + EWL_FLAG_QUEUED_CPROCESS); + } + + DLEAVE_FUNCTION(DLEVEL_STABLE); +} + /** * @internal * @return Returns no value * @brief Configure all the widgets that need to be configured */ static void -ewl_configure_queue(void) +ewl_configure_queue_run(void) { - Ewl_Widget *w; + Ewl_Configure_Queue *queue_buffer; DENTER_FUNCTION(DLEVEL_STABLE); /* * Configure any widgets that need it. */ - while ((w = ecore_list_remove_first(configure_list))) { - if (ewl_object_flags_get(EWL_OBJECT(w), - EWL_FLAG_PROPERTY_TOPLEVEL)) { - ewl_object_size_request(EWL_OBJECT(w), - ewl_object_current_w_get(EWL_OBJECT(w)), - ewl_object_current_h_get(EWL_OBJECT(w))); - } + while ((queue_buffer = ecore_list_remove_first(configure_active))) { + int i; + for (i = 0; i < queue_buffer->end; i++) { + Ewl_Widget *w; - /* - * Remove the flag that the widget is scheduled for - * configuration. - */ - ewl_object_queued_remove(EWL_OBJECT(w), - EWL_FLAG_QUEUED_CSCHEDULED); + w = queue_buffer->buffer[i]; + ewl_configure_queue_widget_run(w); + } /* - * Items that are off screen should be queued to give up their - * evas objects for reuse. Items returning from offscreen are - * queued to receive new evas objects. + * Add to the available list re-initialized. */ - if (!ewl_widget_onscreen_is(w)) { - if (!OBSCURED(w)) - ecore_list_prepend(obscure_list, w); - } - else { - if (OBSCURED(w)) - ecore_list_prepend(reveal_list, w); - - ewl_object_queued_add(EWL_OBJECT(w), - EWL_FLAG_QUEUED_CPROCESS); - if (REALIZED(w) && VISIBLE(w) && !OBSCURED(w)) - ewl_callback_call(w, EWL_CALLBACK_CONFIGURE); - ewl_object_queued_remove(EWL_OBJECT(w), - EWL_FLAG_QUEUED_CPROCESS); - } + queue_buffer->end = 0; + ecore_list_prepend(configure_available, queue_buffer); } DLEAVE_FUNCTION(DLEVEL_STABLE); @@ -807,13 +887,26 @@ static void ewl_configure_cancel_request(Ewl_Widget *w) { + Ewl_Configure_Queue *queue_buffer; DENTER_FUNCTION(DLEVEL_TESTING); - ecore_list_goto(configure_list, w); - if (ecore_list_current(configure_list) == w) { - ewl_object_queued_remove(EWL_OBJECT(w), - EWL_FLAG_QUEUED_CSCHEDULED); - ecore_list_remove(configure_list); + ecore_list_goto_first(configure_active); + while ((queue_buffer = ecore_list_next(configure_active))) { + int i; + for (i = 0; i < queue_buffer->end; i++) { + Ewl_Widget *tmp; + + tmp = queue_buffer->buffer[i]; + if (tmp == w) { + ewl_object_queued_remove(EWL_OBJECT(w), + EWL_FLAG_QUEUED_CSCHEDULED); + if (i < queue_buffer->end - 1) + memmove(queue_buffer->buffer + i, + queue_buffer->buffer + i + 1, + queue_buffer->end - i - 1); + queue_buffer->end--; + } + } } DLEAVE_FUNCTION(DLEVEL_TESTING); ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs