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
This commit is contained in:
Ulisses Furquim 2013-01-06 02:01:53 +00:00
parent 7904f59248
commit d53f43abaf
1 changed files with 19 additions and 23 deletions

View File

@ -7,9 +7,8 @@ static Eina_Condition evas_thread_queue_condition;
static Eina_Lock evas_thread_queue_lock; static Eina_Lock evas_thread_queue_lock;
static Eina_Bool evas_thread_queue_ready = EINA_FALSE; static Eina_Bool evas_thread_queue_ready = EINA_FALSE;
static Eina_Inarray evas_thread_queue; static Eina_Inarray evas_thread_queue;
static Evas_Thread_Command *evas_thread_queue_cache = NULL; 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 volatile int evas_thread_exited = 0;
static Eina_Bool exit_thread = EINA_FALSE; 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); 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); cmd = eina_inarray_grow(&evas_thread_queue, 1);
if (cmd) if (cmd)
{ {
@ -40,6 +30,7 @@ evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flu
else else
{ {
ERR("Out of memory allocating thread command."); ERR("Out of memory allocating thread command.");
goto out;
} }
if (do_flush) 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); eina_condition_signal(&evas_thread_queue_condition);
} }
out:
eina_lock_release(&evas_thread_queue_lock); 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) while (1)
{ {
Evas_Thread_Command *head;
Evas_Thread_Command *cmd; Evas_Thread_Command *cmd;
int len; unsigned int len, max;
int max;
eina_lock_take(&evas_thread_queue_lock); 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)) if (!eina_inarray_count(&evas_thread_queue))
{ {
ERR("Signaled to find an empty queue. BUG!"); ERR("Signaled to find an empty queue. BUG!");
evas_thread_queue_ready = EINA_FALSE;
eina_lock_release(&evas_thread_queue_lock); eina_lock_release(&evas_thread_queue_lock);
continue; continue;
} }
head = evas_thread_queue.members; cmd = evas_thread_queue.members;
evas_thread_queue.members = NULL; evas_thread_queue.members = evas_thread_queue_cache;
max = evas_thread_queue.max; evas_thread_queue.max = 0; evas_thread_queue_cache = cmd;
len = evas_thread_queue.len; evas_thread_queue.len = 0;
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; evas_thread_queue_ready = EINA_FALSE;
eina_lock_release(&evas_thread_queue_lock); eina_lock_release(&evas_thread_queue_lock);
cmd = head; DBG("Evas render thread command queue length: %u", len);
while (len) while (len)
{ {
assert(cmd->cb); assert(cmd->cb);
@ -111,9 +109,6 @@ evas_thread_worker_func(void *data EINA_UNUSED, Eina_Thread thread EINA_UNUSED)
cmd++; cmd++;
len--; len--;
} }
evas_thread_queue_cache = head;
evas_thread_queue_cache_max = max;
} }
out: out:
@ -163,6 +158,7 @@ evas_thread_shutdown(void)
eina_condition_free(&evas_thread_queue_condition); eina_condition_free(&evas_thread_queue_condition);
eina_inarray_flush(&evas_thread_queue); eina_inarray_flush(&evas_thread_queue);
free(evas_thread_queue_cache);
eina_threads_shutdown(); eina_threads_shutdown();
} }