#include "Ecore.h"
#include "ecore_private.h"
-#define MY_CLASS ECORE_IDLER_CLASS
-
-#define MY_CLASS_NAME "Ecore_Idler"
-
-struct _Ecore_Idler_Data
+struct _Ecore_Idler
{
- EINA_INLIST;
- Ecore_Idler *obj;
Ecore_Task_Cb func;
void *data;
- int references;
- Eina_Bool delete_me : 1;
};
-typedef struct _Ecore_Idler_Data Ecore_Idler_Data;
-static Ecore_Idler_Data *idlers = NULL;
-static Ecore_Idler_Data *idler_current = NULL;
-static int idlers_delete_me = 0;
-
-static void *
-_ecore_idler_del(Ecore_Idler *idler);
+static void *_ecore_idler_del(Ecore_Idler *idler);
-EAPI Ecore_Idler *
-ecore_idler_add(Ecore_Task_Cb func,
- const void *data)
+static Eina_Bool
+_ecore_idler_event_del(void *data, const Eo_Event *event EINA_UNUSED)
{
- return eo_add(MY_CLASS, _ecore_parent, ecore_idler_constructor(eo_self, func, data));
+ _ecore_idler_del(data);
+
+ return EO_CALLBACK_CONTINUE;
}
-EOLIAN static void
-_ecore_idler_constructor(Eo *obj, Ecore_Idler_Data *ie, Ecore_Task_Cb func, const void *data)
+static Eina_Bool
+_ecore_idler_process(void *data, const Eo_Event *event EINA_UNUSED)
{
- if (EINA_UNLIKELY(!eina_main_loop_is()))
- {
- EINA_MAIN_LOOP_CHECK_RETURN;
- }
+ Ecore_Idler *idler = data;
- ie->obj = obj;
- eo_manual_free_set(obj, EINA_TRUE);
+ if (!_ecore_call_task_cb(idler->func, idler->data))
+ _ecore_idler_del(idler);
- if (!func)
- {
- ERR("callback function must be set up for an object of class: '%s'", MY_CLASS_NAME);
- return;
- }
-
- ie->func = func;
- ie->data = (void *)data;
- idlers = (Ecore_Idler_Data *)eina_inlist_append(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
+ return EO_CALLBACK_CONTINUE;
}
-EAPI void *
-ecore_idler_del(Ecore_Idler *idler)
-{
- if (!idler) return NULL;
- EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
-
- return _ecore_idler_del(idler);
-}
+EO_CALLBACKS_ARRAY_DEFINE(ecore_idler_callbacks,
+ { ECORE_MAINLOOP_EVENT_IDLE, _ecore_idler_process },
+ { EO_BASE_EVENT_DEL, _ecore_idler_event_del });
static void *
-_ecore_idler_del(Ecore_Idler *obj)
+_ecore_idler_del(Ecore_Idler *idler)
{
- Ecore_Idler_Data *idler = eo_data_scope_get(obj, MY_CLASS);
+ void *data;
+
if (!idler) return NULL;
- EINA_SAFETY_ON_TRUE_RETURN_VAL(idler->delete_me, NULL);
- idler->delete_me = 1;
- idlers_delete_me = 1;
- return idler->data;
-}
-EOLIAN static void
-_ecore_idler_eo_base_destructor(Eo *obj, Ecore_Idler_Data *idler)
-{
- idler->delete_me = 1;
- idlers_delete_me = 1;
+ eo_event_callback_array_del(_mainloop_singleton, ecore_idler_callbacks(), idler);
- eo_destructor(eo_super(obj, MY_CLASS));
+ data = idler->data;
+ free(idler);
+ return data;
}
-EOLIAN static Eo *
-_ecore_idler_eo_base_finalize(Eo *obj, Ecore_Idler_Data *idler)
+EAPI Ecore_Idler *
+ecore_idler_add(Ecore_Task_Cb func,
+ const void *data)
{
- if (!idler->func)
+ Ecore_Idler *ret;
+
+ if (EINA_UNLIKELY(!eina_main_loop_is()))
{
+ EINA_MAIN_LOOP_CHECK_RETURN;
+ }
+
+ if (!func)
+ {
+ ERR("callback function must be set up for an object of Ecore_Idler.");
return NULL;
}
- return eo_finalize(eo_super(obj, MY_CLASS));
+ ret = malloc(sizeof (Ecore_Idler));
+ if (!ret) return NULL;
+
+ ret->func = func;
+ ret->data = (void*) data;
+
+ eo_event_callback_array_add(_mainloop_singleton, ecore_idler_callbacks(), ret);
+
+ return ret;
}
-void
-_ecore_idler_shutdown(void)
+EAPI void *
+ecore_idler_del(Ecore_Idler *idler)
{
- Ecore_Idler_Data *ie;
- while ((ie = idlers))
- {
- idlers = (Ecore_Idler_Data *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(idlers));
+ if (!idler) return NULL;
+ EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
- eo_parent_set(ie->obj, NULL);
- if (eo_destructed_is(ie->obj))
- eo_manual_free(ie->obj);
- else
- eo_manual_free_set(ie->obj, EINA_FALSE);
- }
- idlers_delete_me = 0;
- idler_current = NULL;
+ return _ecore_idler_del(idler);
}
-int
-_ecore_idler_all_call(void)
+void
+_ecore_idler_all_call(Eo *loop)
{
- if (!idler_current)
- {
- /* regular main loop, start from head */
- idler_current = idlers;
- }
- else
- {
- /* recursive main loop, continue from where we were */
- idler_current = (Ecore_Idler_Data *)EINA_INLIST_GET(idler_current)->next;
- }
-
- while (idler_current)
- {
- Ecore_Idler_Data *ie = (Ecore_Idler_Data *)idler_current;
- if (!ie->delete_me)
- {
- ie->references++;
- eina_evlog("+idler", ie, 0.0, NULL);
- if (!_ecore_call_task_cb(ie->func, ie->data))
- {
- if (!ie->delete_me) _ecore_idler_del(ie->obj);
- }
- eina_evlog("-idler", ie, 0.0, NULL);
- ie->references--;
- }
- if (idler_current) /* may have changed in recursive main loops */
- idler_current = (Ecore_Idler_Data *)EINA_INLIST_GET(idler_current)->next;
- }
- if (idlers_delete_me)
- {
- Ecore_Idler_Data *l;
- int deleted_idlers_in_use = 0;
- for (l = idlers; l; )
- {
- Ecore_Idler_Data *ie = l;
- l = (Ecore_Idler_Data *)EINA_INLIST_GET(l)->next;
- if (ie->delete_me)
- {
- if (ie->references)
- {
- deleted_idlers_in_use++;
- continue;
- }
-
- idlers = (Ecore_Idler_Data *)eina_inlist_remove(EINA_INLIST_GET(idlers), EINA_INLIST_GET(ie));
-
- eo_parent_set(ie->obj, NULL);
- if (eo_destructed_is(ie->obj))
- eo_manual_free(ie->obj);
- else
- eo_manual_free_set(ie->obj, EINA_FALSE);
- }
- }
- if (!deleted_idlers_in_use)
- idlers_delete_me = 0;
- }
- if (idlers) return 1;
- return 0;
+ eo_event_callback_call(loop, ECORE_MAINLOOP_EVENT_IDLE, NULL);
}
int
-_ecore_idler_exist(void)
+_ecore_idler_exist(Eo *loop)
{
- if (idlers) return 1;
- return 0;
-}
+ Ecore_Mainloop_Data *dt = eo_data_scope_get(loop, ECORE_MAINLOOP_CLASS);
-#include "ecore_idler.eo.c"
+ return dt->idlers;
+}
if (g_main_loop_is_running(ecore_main_loop))
{
/* only set idling state in dispatch */
- if (ecore_idling && !_ecore_idler_exist() && !_ecore_event_exist())
+ if (ecore_idling && !_ecore_idler_exist(_mainloop_singleton) && !_ecore_event_exist())
{
if (_ecore_timers_exists())
{
in_main_loop++;
/* check if old timers expired */
- if (ecore_idling && !_ecore_idler_exist() && !_ecore_event_exist())
+ if (ecore_idling && !_ecore_idler_exist(_mainloop_singleton) && !_ecore_event_exist())
{
if (timer_fd >= 0)
{
events_ready = _ecore_event_exist();
timers_ready = _ecore_timers_exists() && (0.0 == next_time);
- idlers_ready = _ecore_idler_exist();
+ idlers_ready = _ecore_idler_exist(_mainloop_singleton);
in_main_loop++;
DBG("enter idling=%d fds=%d events=%d timers=%d (next=%.2f) idlers=%d",
if (ecore_idling)
{
- _ecore_idler_all_call();
+ _ecore_idler_all_call(_mainloop_singleton);
events_ready = _ecore_event_exist();
double t = -1;
if(_ecore_main_uv_idling)
{
- _ecore_idler_all_call();
+ _ecore_idler_all_call(_mainloop_singleton);
DBG("called idles");
- if(_ecore_idler_exist() || _ecore_event_exist())
+ if(_ecore_idler_exist(_mainloop_singleton) || _ecore_event_exist())
t = 0.0;
}
{
/* as we are spinning we need to update loop time per spin */
_ecore_time_loop_time = ecore_time_get();
- /* call all idlers, which returns false if no more idelrs exist */
- if (!_ecore_idler_all_call()) return SPIN_RESTART;
+ /* call all idlers */
+ _ecore_idler_all_call(_mainloop_singleton);
+ /* which returns false if no more idelrs exist */
+ if (!_ecore_idler_exist(_mainloop_singleton)) return SPIN_RESTART;
/* sneaky - drop through or if checks - the first one to succeed
* drops through and returns "continue" so further ones dont run */
if ((_ecore_main_select(0.0) > 0) || (_ecore_event_exist()) ||
/* init flags */
next_time = _ecore_timer_next_get();
/* no idlers */
- if (!_ecore_idler_exist())
+ if (!_ecore_idler_exist(_mainloop_singleton))
{
/* sleep until timeout or forever (-1.0) waiting for on fds */
_ecore_main_select(next_time);
return ecore_main_loop_animator_ticked_get();
}
+static Eina_Bool
+_check_event_catcher_add(void *data, const Eo_Event *event)
+{
+ const Eo_Callback_Array_Item *array = event->info;
+ Ecore_Mainloop_Data *pd = data;
+ int i;
+
+ for (i = 0; array[i].desc != NULL; i++)
+ {
+ if (array[i].desc == ECORE_MAINLOOP_EVENT_IDLE)
+ {
+ ++pd->idlers;
+ }
+ }
+
+ return EO_CALLBACK_CONTINUE;
+}
+
+static Eina_Bool
+_check_event_catcher_del(void *data, const Eo_Event *event)
+{
+ const Eo_Callback_Array_Item *array = event->info;
+ Ecore_Mainloop_Data *pd = data;
+ int i;
+
+ for (i = 0; array[i].desc != NULL; i++)
+ {
+ if (array[i].desc == ECORE_MAINLOOP_EVENT_IDLE)
+ {
+ --pd->idlers;
+ }
+ }
+
+ return EO_CALLBACK_CONTINUE;
+}
+
+EO_CALLBACKS_ARRAY_DEFINE(event_catcher_watch,
+ { EO_BASE_EVENT_CALLBACK_ADD, _check_event_catcher_add },
+ { EO_BASE_EVENT_CALLBACK_DEL, _check_event_catcher_del });
+
+EOLIAN static Eo_Base *
+_ecore_mainloop_eo_base_constructor(Eo *obj, Ecore_Mainloop_Data *pd)
+{
+ eo_constructor(eo_super(obj, ECORE_MAINLOOP_CLASS));
+ eo_event_callback_array_add(obj, event_catcher_watch(), pd);
+
+ return obj;
+}
+
#include "ecore_mainloop.eo.c"