From d53f43abaf440d2356c91fa809ad636daa176d7f Mon Sep 17 00:00:00 2001 From: Ulisses Furquim Date: Sun, 6 Jan 2013 02:01:53 +0000 Subject: [PATCH] evas/common/thread_render: fix queue cache handling Fixed queue cache handling to let enqueue and process happen at the same time, even though this is not our use case yet. This also solves a race with the assignment of cache variables outside the queue lock and remembers to free the cache when shutting down. SVN revision: 82296 --- src/lib/evas/common/evas_thread_render.c | 42 +++++++++++------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/lib/evas/common/evas_thread_render.c b/src/lib/evas/common/evas_thread_render.c index 9c434c29e2..40964ba7ec 100644 --- a/src/lib/evas/common/evas_thread_render.c +++ b/src/lib/evas/common/evas_thread_render.c @@ -7,9 +7,8 @@ static Eina_Condition evas_thread_queue_condition; static Eina_Lock evas_thread_queue_lock; static Eina_Bool evas_thread_queue_ready = EINA_FALSE; static Eina_Inarray evas_thread_queue; - static Evas_Thread_Command *evas_thread_queue_cache = NULL; -static int evas_thread_queue_cache_max = 0; +static unsigned int evas_thread_queue_cache_max = 0; static volatile int evas_thread_exited = 0; static Eina_Bool exit_thread = EINA_FALSE; @@ -22,15 +21,6 @@ evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flu eina_lock_take(&evas_thread_queue_lock); - if (evas_thread_queue.members == NULL) - { - evas_thread_queue.members = evas_thread_queue_cache; - evas_thread_queue.len = 0; - evas_thread_queue.max = evas_thread_queue_cache_max; - evas_thread_queue_cache = NULL; - evas_thread_queue_cache_max = 0; - } - cmd = eina_inarray_grow(&evas_thread_queue, 1); if (cmd) { @@ -40,6 +30,7 @@ evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flu else { ERR("Out of memory allocating thread command."); + goto out; } if (do_flush) @@ -48,6 +39,7 @@ evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flu eina_condition_signal(&evas_thread_queue_condition); } +out: eina_lock_release(&evas_thread_queue_lock); } @@ -68,10 +60,8 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED) { while (1) { - Evas_Thread_Command *head; Evas_Thread_Command *cmd; - int len; - int max; + unsigned int len, max; eina_lock_take(&evas_thread_queue_lock); @@ -88,20 +78,28 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED) if (!eina_inarray_count(&evas_thread_queue)) { ERR("Signaled to find an empty queue. BUG!"); + evas_thread_queue_ready = EINA_FALSE; eina_lock_release(&evas_thread_queue_lock); continue; } - head = evas_thread_queue.members; - evas_thread_queue.members = NULL; - max = evas_thread_queue.max; evas_thread_queue.max = 0; - len = evas_thread_queue.len; evas_thread_queue.len = 0; - + cmd = evas_thread_queue.members; + evas_thread_queue.members = evas_thread_queue_cache; + evas_thread_queue_cache = cmd; + + max = evas_thread_queue.max; + evas_thread_queue.max = evas_thread_queue_cache_max; + evas_thread_queue_cache_max = max; + + len = evas_thread_queue.len; + evas_thread_queue.len = 0; + evas_thread_queue_ready = EINA_FALSE; eina_lock_release(&evas_thread_queue_lock); - cmd = head; + DBG("Evas render thread command queue length: %u", len); + while (len) { assert(cmd->cb); @@ -111,9 +109,6 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED) cmd++; len--; } - - evas_thread_queue_cache = head; - evas_thread_queue_cache_max = max; } out: @@ -163,6 +158,7 @@ evas_thread_shutdown(void) eina_condition_free(&evas_thread_queue_condition); eina_inarray_flush(&evas_thread_queue); + free(evas_thread_queue_cache); eina_threads_shutdown(); }