static int _fd_read = -1;
static pid_t _fd_pid = 0;
+static Eina_Lock async_lock;
+static Eina_Inarray async_queue;
+
static int _init_evas_event = 0;
typedef struct _Evas_Event_Async Evas_Event_Async;
fcntl(_fd_read, F_SETFL, O_NONBLOCK);
+ eina_lock_new(&async_lock);
+ eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16);
+
return _init_evas_event;
}
_fd_read = -1;
_fd_write = -1;
+ eina_lock_free(&async_lock);
+ eina_inarray_flush(&async_queue);
+
return _init_evas_event;
}
static int
_evas_async_events_process_single(void)
{
- Evas_Event_Async *ev;
+ int wakeup;
int ret;
- ret = read(_fd_read, &ev, sizeof(Evas_Event_Async *));
- if (ret == sizeof(Evas_Event_Async *))
+ ret = read(_fd_read, &wakeup, sizeof(int));
+ if (ret == sizeof(int))
{
- if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
- free(ev);
- return 1;
+ static Evas_Event_Async *memory = NULL;
+ static unsigned int memory_max = 0;
+ Evas_Event_Async *ev;
+ unsigned int len;
+ unsigned int max;
+
+ eina_lock_take(&async_lock);
+
+ ev = async_queue.members;
+ async_queue.members = memory;
+ memory = ev;
+
+ max = async_queue.max;
+ async_queue.max = memory_max;
+ memory_max = max;
+
+ len = async_queue.len;
+ async_queue.len = 0;
+
+ eina_lock_release(&async_lock);
+
+ while (len > 0)
+ {
+ if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
+ ev++;
+ len--;
+ }
+ ret = 1;
}
else if (ret < 0)
{
evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_info, Evas_Async_Events_Put_Cb func)
{
Evas_Event_Async *ev;
- ssize_t check;
+ ssize_t check = sizeof (int);
Eina_Bool result = EINA_FALSE;
+ int count;
if (!func) return 0;
if (_fd_write == -1) return 0;
_evas_async_events_fork_handle();
-
- ev = calloc(1, sizeof (Evas_Event_Async));
- if (!ev) return 0;
- ev->func = func;
- ev->target = target;
- ev->type = type;
- ev->event_info = event_info;
+ eina_lock_take(&async_lock);
+
+ count = async_queue.len;
+ ev = eina_inarray_add(&async_queue);
+ if (ev)
+ {
+ ev->func = func;
+ ev->target = target;
+ ev->type = type;
+ ev->event_info = event_info;
+ }
+
+ eina_lock_release(&async_lock);
- do
+ if (count == 0 && ev)
{
- check = write(_fd_write, &ev, sizeof (Evas_Event_Async*));
+ int wakeup = 1;
+
+ do
+ {
+ check = write(_fd_write, &wakeup, sizeof (int));
+ }
+ while ((check != sizeof (int)) &&
+ ((errno == EINTR) || (errno == EAGAIN)));
}
- while ((check != sizeof (Evas_Event_Async*)) &&
- ((errno == EINTR) || (errno == EAGAIN)));
evas_cache_image_wakeup();
- if (check == sizeof (Evas_Event_Async*))
+ if (check == sizeof (int))
result = EINA_TRUE;
else
{
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_Inlist *evas_thread_queue = NULL;
+static Eina_Inarray evas_thread_queue;
+
+static Evas_Thread_Command *evas_thread_queue_cache = NULL;
+static int evas_thread_queue_cache_max = 0;
+
static volatile int evas_thread_exited = 0;
static Eina_Bool exit_thread = EINA_FALSE;
static int init_count = 0;
-static Evas_Thread_Command *
-evas_thread_cmd_new(Evas_Thread_Command_Cb cb, void *data, size_t size)
-{
- Evas_Thread_Command *cmd = malloc(sizeof(*cmd) + size);
- if (!cmd)
- {
- ERR("Out of memory allocating thread command.");
- return NULL;
- }
-
- cmd->cb = cb;
- if (size)
- {
- cmd->data = cmd + 1;
- memcpy(cmd->data, data, size);
- }
- else
- cmd->data = data;
-
- return cmd;
-}
-
static void
-evas_thread_queue_append(Evas_Thread_Command *cmd, Eina_Bool do_flush)
+evas_thread_queue_append(Evas_Thread_Command_Cb cb, void *data, Eina_Bool do_flush)
{
- eina_lock_take(&evas_thread_queue_lock);
-
- evas_thread_queue = eina_inlist_append(evas_thread_queue, EINA_INLIST_GET(cmd));
-
- if (do_flush)
- {
- evas_thread_queue_ready = EINA_TRUE;
- eina_condition_signal(&evas_thread_queue_condition);
- }
-
- eina_lock_release(&evas_thread_queue_lock);
+ Evas_Thread_Command *cmd;
+
+ 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_add(&evas_thread_queue);
+ if (cmd)
+ {
+ cmd->cb = cb;
+ cmd->data = data;
+ }
+ else
+ {
+ ERR("Out of memory allocating thread command.");
+ }
+
+ if (do_flush)
+ {
+ evas_thread_queue_ready = EINA_TRUE;
+ eina_condition_signal(&evas_thread_queue_condition);
+ }
+
+ eina_lock_release(&evas_thread_queue_lock);
}
EAPI void
-evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data, size_t size)
+evas_thread_cmd_enqueue(Evas_Thread_Command_Cb cb, void *data)
{
- Evas_Thread_Command *cmd = evas_thread_cmd_new(cb, data, size);
- if (!cmd)
- return;
-
- evas_thread_queue_append(cmd, EINA_FALSE);
+ evas_thread_queue_append(cb, data, EINA_FALSE);
}
EAPI void
-evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data, size_t size)
+evas_thread_queue_flush(Evas_Thread_Command_Cb cb, void *data)
{
- Evas_Thread_Command *cmd = evas_thread_cmd_new(cb, data, size);
- if (!cmd)
- return;
-
- evas_thread_queue_append(cmd, EINA_TRUE);
+ evas_thread_queue_append(cb, data, EINA_TRUE);
}
static void*
{
while (1)
{
+ Evas_Thread_Command *head;
Evas_Thread_Command *cmd;
- Eina_Inlist *queue;
+ int len;
+ int max;
eina_lock_take(&evas_thread_queue_lock);
eina_condition_wait(&evas_thread_queue_condition);
}
- if (!evas_thread_queue)
+ if (!eina_inarray_count(&evas_thread_queue))
{
ERR("Signaled to find an empty queue. BUG!");
eina_lock_release(&evas_thread_queue_lock);
continue;
}
- queue = evas_thread_queue;
- evas_thread_queue = NULL;
+ 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;
+
evas_thread_queue_ready = EINA_FALSE;
eina_lock_release(&evas_thread_queue_lock);
- while (queue)
+ cmd = head;
+ while (len)
{
- cmd = EINA_INLIST_CONTAINER_GET(queue, Evas_Thread_Command);
-
- assert(cmd);
assert(cmd->cb);
cmd->cb(cmd->data);
- queue = eina_inlist_remove(queue, queue);
- free(cmd);
+ cmd++;
+ len--;
}
+
+ evas_thread_queue_cache = head;
+ evas_thread_queue_cache_max = max;
}
out:
eina_threads_init();
+ eina_inarray_step_set(&evas_thread_queue, sizeof (Eina_Inarray), sizeof (Evas_Thread_Command), 128);
+
if (!eina_lock_new(&evas_thread_queue_lock))
CRIT("Could not create draw thread lock");
if (!eina_condition_new(&evas_thread_queue_condition, &evas_thread_queue_lock))
eina_lock_free(&evas_thread_queue_lock);
eina_condition_free(&evas_thread_queue_condition);
+ eina_inarray_flush(&evas_thread_queue);
+
eina_threads_shutdown();
}