forked from enlightenment/efl
139 lines
3.2 KiB
C
139 lines
3.2 KiB
C
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <Eo.h>
|
|
|
|
#include "Ecore.h"
|
|
#include "ecore_private.h"
|
|
|
|
struct _Ecore_Factorized_Idle
|
|
{
|
|
Ecore_Task_Cb func;
|
|
void *data;
|
|
|
|
const Efl_Callback_Array_Item *desc;
|
|
|
|
short references;
|
|
Eina_Bool delete_me : 1;
|
|
};
|
|
|
|
void
|
|
_ecore_factorized_idle_event_del(void *data, const Efl_Event *event EINA_UNUSED)
|
|
{
|
|
_ecore_factorized_idle_del(data);
|
|
}
|
|
|
|
void
|
|
_ecore_factorized_idle_process(void *data, const Efl_Event *event EINA_UNUSED)
|
|
{
|
|
Ecore_Factorized_Idle *idler = data;
|
|
|
|
idler->references++;
|
|
if (!_ecore_call_task_cb(idler->func, idler->data))
|
|
idler->delete_me = EINA_TRUE;
|
|
idler->references--;
|
|
|
|
if (idler->delete_me &&
|
|
idler->references == 0)
|
|
_ecore_factorized_idle_del(idler);
|
|
}
|
|
|
|
static Eina_Mempool *idler_mp = NULL;
|
|
|
|
void *
|
|
_ecore_factorized_idle_del(Ecore_Idler *idler)
|
|
{
|
|
void *data;
|
|
|
|
if (!idler) return NULL;
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
|
|
|
if (idler->references > 0)
|
|
{
|
|
idler->delete_me = EINA_TRUE;
|
|
return idler->data;
|
|
}
|
|
|
|
efl_event_callback_array_del(_mainloop_singleton, idler->desc, idler);
|
|
|
|
data = idler->data;
|
|
eina_mempool_free(idler_mp, idler);
|
|
return data;
|
|
}
|
|
|
|
Ecore_Factorized_Idle *
|
|
_ecore_factorized_idle_add(const Efl_Callback_Array_Item *desc,
|
|
Ecore_Task_Cb func,
|
|
const void *data)
|
|
{
|
|
Ecore_Factorized_Idle *ret;
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
|
|
|
if (!func)
|
|
{
|
|
ERR("callback function must be set up for an object of Ecore_Idler.");
|
|
return NULL;
|
|
}
|
|
|
|
if (!idler_mp)
|
|
{
|
|
idler_mp = eina_mempool_add("chained_mempool", "Ecore_Idle*", NULL, sizeof (Ecore_Factorized_Idle), 23);
|
|
if (!idler_mp) return NULL;
|
|
}
|
|
|
|
ret = eina_mempool_malloc(idler_mp, sizeof (Ecore_Factorized_Idle));
|
|
if (!ret) return NULL;
|
|
|
|
ret->func = func;
|
|
ret->data = (void*) data;
|
|
ret->desc = desc;
|
|
ret->references = 0;
|
|
ret->delete_me = EINA_FALSE;
|
|
|
|
efl_event_callback_array_add(_mainloop_singleton, desc, ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Specific to Ecore_Idler implementation */
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(ecore_idler_callbacks,
|
|
{ EFL_LOOP_EVENT_IDLE, _ecore_factorized_idle_process },
|
|
{ EFL_EVENT_DEL, _ecore_factorized_idle_event_del });
|
|
|
|
EAPI Ecore_Idler *
|
|
ecore_idler_add(Ecore_Task_Cb func,
|
|
const void *data)
|
|
{
|
|
return _ecore_factorized_idle_add(ecore_idler_callbacks(), func, data);
|
|
}
|
|
|
|
EAPI void *
|
|
ecore_idler_del(Ecore_Idler *idler)
|
|
{
|
|
return _ecore_factorized_idle_del(idler);
|
|
}
|
|
|
|
void
|
|
_ecore_idler_all_call(Eo *loop)
|
|
{
|
|
efl_event_callback_call(loop, EFL_LOOP_EVENT_IDLE, NULL);
|
|
// just spin in an idler until the free queue is empty freeing 84 items
|
|
// from the free queue each time.for now this seems like an ok balance
|
|
// between going in and out of a reduce func with mutexes around it
|
|
// vs blocking mainloop for too long. this number is up for discussion
|
|
eina_freeq_reduce(eina_freeq_main_get(), 84);
|
|
}
|
|
|
|
int
|
|
_ecore_idler_exist(Eo *loop)
|
|
{
|
|
Efl_Loop_Data *dt = efl_data_scope_get(loop, EFL_LOOP_CLASS);
|
|
|
|
return dt->idlers || eina_freeq_ptr_pending(eina_freeq_main_get());
|
|
}
|