2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2012-11-18 22:26:48 -08:00
|
|
|
#include <Eo.h>
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
#include "Ecore.h"
|
2009-12-22 13:15:12 -08:00
|
|
|
#include "ecore_private.h"
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2016-06-03 16:01:08 -07:00
|
|
|
#define MY_CLASS EFL_LOOP_TIMER_CLASS
|
|
|
|
#define MY_CLASS_NAME "Efl_Loop_Timer"
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
#define ECORE_TIMER_CHECK(obj) if (!efl_isa((obj), MY_CLASS)) return
|
|
|
|
|
|
|
|
struct _Ecore_Timer_Legacy
|
|
|
|
{
|
|
|
|
Ecore_Task_Cb func;
|
|
|
|
|
|
|
|
const void *data;
|
|
|
|
|
|
|
|
Eina_Bool inside_call : 1;
|
|
|
|
Eina_Bool delete_me : 1;
|
|
|
|
};
|
2019-10-28 11:59:11 -07:00
|
|
|
typedef struct _Ecore_Timer_Legacy Ecore_Timer_Legacy;
|
2016-06-03 16:01:08 -07:00
|
|
|
struct _Efl_Loop_Timer_Data
|
2011-12-11 00:29:35 -08:00
|
|
|
{
|
|
|
|
EINA_INLIST;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
|
|
|
Eo *object;
|
2017-11-08 22:59:04 -08:00
|
|
|
Eo *loop;
|
|
|
|
Efl_Loop_Data *loop_data;
|
2019-10-28 11:59:11 -07:00
|
|
|
Ecore_Timer_Legacy *legacy;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
double in;
|
|
|
|
double at;
|
|
|
|
double pending;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
int listening;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
Eina_Bool just_added : 1;
|
|
|
|
Eina_Bool frozen : 1;
|
|
|
|
Eina_Bool initialized : 1;
|
|
|
|
Eina_Bool noparent : 1;
|
|
|
|
Eina_Bool constructed : 1;
|
|
|
|
Eina_Bool finalized : 1;
|
2011-12-11 00:29:35 -08:00
|
|
|
};
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
static void _efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add);
|
|
|
|
static void _efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer);
|
|
|
|
static void _efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in);
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static double precision = 10.0 / 1000000.0;
|
2010-10-17 00:03:28 -07:00
|
|
|
|
2008-11-13 12:42:01 -08:00
|
|
|
EAPI double
|
|
|
|
ecore_timer_precision_get(void)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
|
2008-11-13 12:42:01 -08:00
|
|
|
return precision;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
|
|
|
ecore_timer_precision_set(double value)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2017-11-08 22:59:04 -08:00
|
|
|
if (value < 0.0) value = 0.0;
|
2008-11-13 12:42:01 -08:00
|
|
|
precision = value;
|
|
|
|
}
|
|
|
|
|
2016-06-20 07:31:31 -07:00
|
|
|
static void
|
2016-08-30 05:34:10 -07:00
|
|
|
_check_timer_event_catcher_add(void *data, const Efl_Event *event)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer = data;
|
2018-02-27 04:19:17 -08:00
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
2016-05-04 13:37:39 -07:00
|
|
|
int i;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
2019-03-08 07:33:05 -08:00
|
|
|
if (array[i].desc == EFL_LOOP_TIMER_EVENT_TIMER_TICK)
|
2016-05-04 13:37:39 -07:00
|
|
|
{
|
2016-06-20 07:31:31 -07:00
|
|
|
if (timer->listening++ > 0) return;
|
2019-10-24 08:22:17 -07:00
|
|
|
if (timer->finalized)
|
|
|
|
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
|
2016-05-04 13:37:39 -07:00
|
|
|
// No need to walk more than once per array as you can not del
|
|
|
|
// a partial array
|
2016-06-20 07:31:31 -07:00
|
|
|
return;
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
|
|
|
|
2016-06-20 07:31:31 -07:00
|
|
|
static void
|
2016-08-30 05:34:10 -07:00
|
|
|
_check_timer_event_catcher_del(void *data, const Efl_Event *event)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer = data;
|
2018-02-27 04:19:17 -08:00
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
2016-05-04 13:37:39 -07:00
|
|
|
int i;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2019-03-08 07:33:05 -08:00
|
|
|
if (array[i].desc == EFL_LOOP_TIMER_EVENT_TIMER_TICK)
|
2016-05-04 13:37:39 -07:00
|
|
|
{
|
2016-06-20 07:31:31 -07:00
|
|
|
if ((--timer->listening) > 0) return;
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
|
2016-06-20 07:31:31 -07:00
|
|
|
return;
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(timer_watch,
|
2016-08-10 07:23:04 -07:00
|
|
|
{ EFL_EVENT_CALLBACK_ADD, _check_timer_event_catcher_add },
|
|
|
|
{ EFL_EVENT_CALLBACK_DEL, _check_timer_event_catcher_del });
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
EOLIAN static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_loop_timer_efl_object_constructor(Eo *obj, Efl_Loop_Timer_Data *timer)
|
2016-05-04 13:37:39 -07:00
|
|
|
{
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_constructor(efl_super(obj, MY_CLASS));
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_event_callback_array_add(obj, timer_watch(), timer);
|
|
|
|
efl_wref_add(obj, &timer->object);
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-02-06 15:35:48 -08:00
|
|
|
timer->in = -1.0;
|
2017-11-08 22:59:04 -08:00
|
|
|
timer->constructed = EINA_TRUE;
|
2016-05-04 13:37:39 -07:00
|
|
|
return obj;
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
EOLIAN static Eo *
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_loop_timer_efl_object_finalize(Eo *obj, Efl_Loop_Timer_Data *pd)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
|
|
|
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
|
2017-02-02 16:52:10 -08:00
|
|
|
|
2017-12-26 08:40:07 -08:00
|
|
|
if (pd->at < efl_loop_time_get(pd->loop))
|
|
|
|
pd->at = ecore_time_get() + pd->in;
|
|
|
|
else pd->at += pd->in;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (pd->in < 0.0)
|
2017-02-06 15:35:48 -08:00
|
|
|
{
|
|
|
|
ERR("You need to specify the interval of a timer to create a valid timer.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-02-06 14:29:56 -08:00
|
|
|
pd->initialized = EINA_TRUE;
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->finalized = EINA_TRUE;
|
2017-02-06 14:29:56 -08:00
|
|
|
_efl_loop_timer_set(pd, pd->at, pd->in);
|
2016-08-15 06:44:41 -07:00
|
|
|
return efl_finalize(efl_super(obj, MY_CLASS));
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-06-20 07:31:31 -07:00
|
|
|
static void
|
2016-08-30 05:34:10 -07:00
|
|
|
_ecore_timer_legacy_del(void *data, const Efl_Event *event EINA_UNUSED)
|
2016-05-05 21:55:43 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
free(data);
|
2016-05-05 21:55:43 -07:00
|
|
|
}
|
|
|
|
|
2016-06-20 07:31:31 -07:00
|
|
|
static void
|
2016-08-30 05:34:10 -07:00
|
|
|
_ecore_timer_legacy_tick(void *data, const Efl_Event *event)
|
2016-05-04 13:37:39 -07:00
|
|
|
{
|
|
|
|
Ecore_Timer_Legacy *legacy = data;
|
2019-10-28 11:59:11 -07:00
|
|
|
Eina_Bool inside_call = legacy->inside_call;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2016-05-05 21:55:43 -07:00
|
|
|
legacy->inside_call = 1;
|
2019-10-28 11:59:11 -07:00
|
|
|
if (!_ecore_call_task_cb(legacy->func, (void *)legacy->data) || legacy->delete_me)
|
|
|
|
{
|
|
|
|
legacy->delete_me = EINA_TRUE;
|
|
|
|
/* cannot destroy timer if recursing */
|
|
|
|
if (!inside_call)
|
|
|
|
efl_del(event->object);
|
|
|
|
}
|
|
|
|
/* only unset flag if not currently recursing */
|
|
|
|
else if (!inside_call)
|
|
|
|
legacy->inside_call = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(legacy_timer,
|
2019-03-08 07:33:05 -08:00
|
|
|
{ EFL_LOOP_TIMER_EVENT_TIMER_TICK, _ecore_timer_legacy_tick },
|
2016-08-10 07:23:04 -07:00
|
|
|
{ EFL_EVENT_DEL, _ecore_timer_legacy_del });
|
2016-05-05 21:55:43 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
EAPI Ecore_Timer *
|
2017-11-08 22:59:04 -08:00
|
|
|
ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
Ecore_Timer_Legacy *legacy;
|
2019-10-28 11:59:11 -07:00
|
|
|
Efl_Loop_Timer_Data *td;
|
2016-05-04 13:37:39 -07:00
|
|
|
Eo *timer;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-07-13 16:55:03 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2018-01-29 21:43:11 -08:00
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("Callback function must be set up for the class.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-04-19 21:29:46 -07:00
|
|
|
legacy = calloc(1, sizeof (Ecore_Timer_Legacy));
|
|
|
|
if (!legacy) return NULL;
|
2016-05-04 13:37:39 -07:00
|
|
|
legacy->func = func;
|
|
|
|
legacy->data = data;
|
2018-02-26 21:10:12 -08:00
|
|
|
timer = efl_add(MY_CLASS, efl_main_loop_get(),
|
2016-09-05 08:57:35 -07:00
|
|
|
efl_event_callback_array_add(efl_added, legacy_timer(), legacy),
|
|
|
|
efl_loop_timer_interval_set(efl_added, in));
|
2019-10-28 11:59:11 -07:00
|
|
|
td = efl_data_scope_get(timer, MY_CLASS);
|
|
|
|
td->legacy = legacy;
|
2016-05-04 13:37:39 -07:00
|
|
|
return timer;
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
|
|
|
|
2009-03-22 19:13:50 -07:00
|
|
|
EAPI Ecore_Timer *
|
2017-11-08 22:59:04 -08:00
|
|
|
ecore_timer_loop_add(double in, Ecore_Task_Cb func, const void *data)
|
2009-03-22 19:13:50 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
Ecore_Timer_Legacy *legacy;
|
2019-10-28 11:59:11 -07:00
|
|
|
Efl_Loop_Timer_Data *td;
|
2016-05-04 13:37:39 -07:00
|
|
|
Eo *timer;
|
|
|
|
|
2016-07-13 16:55:03 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2018-01-29 21:43:11 -08:00
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("Callback function must be set up for the class.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-04-08 19:46:13 -07:00
|
|
|
legacy = calloc(1, sizeof (Ecore_Timer_Legacy));
|
|
|
|
if (!legacy) return NULL;
|
2016-05-04 13:37:39 -07:00
|
|
|
legacy->func = func;
|
|
|
|
legacy->data = data;
|
2018-02-26 21:10:12 -08:00
|
|
|
timer = efl_add(MY_CLASS, efl_main_loop_get(),
|
2016-09-05 08:57:35 -07:00
|
|
|
efl_event_callback_array_add(efl_added, legacy_timer(), legacy),
|
|
|
|
efl_loop_timer_loop_reset(efl_added),
|
|
|
|
efl_loop_timer_interval_set(efl_added, in));
|
2019-10-28 11:59:11 -07:00
|
|
|
td = efl_data_scope_get(timer, MY_CLASS);
|
|
|
|
td->legacy = legacy;
|
2016-05-04 13:37:39 -07:00
|
|
|
return timer;
|
2009-03-22 19:13:50 -07:00
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_timer_del(Ecore_Timer *timer)
|
|
|
|
{
|
2019-10-28 11:59:11 -07:00
|
|
|
Efl_Loop_Timer_Data *td;
|
2016-05-04 13:37:39 -07:00
|
|
|
void *data;
|
|
|
|
|
2012-12-24 01:35:56 -08:00
|
|
|
if (!timer) return NULL;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2019-10-28 11:59:11 -07:00
|
|
|
|
|
|
|
td = efl_data_scope_safe_get(timer, MY_CLASS);
|
2016-06-15 10:45:40 -07:00
|
|
|
// If legacy == NULL, this means double free or something
|
2019-10-28 11:59:11 -07:00
|
|
|
if ((!td) || (!td->legacy))
|
2016-06-15 10:45:40 -07:00
|
|
|
{
|
|
|
|
// Just in case it is an Eo timer, but not a legacy one.
|
|
|
|
ERR("You are trying to destroy a timer which seems dead already.");
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_unref(timer);
|
2016-06-15 10:45:40 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-28 11:59:11 -07:00
|
|
|
data = (void *)td->legacy->data;
|
|
|
|
if (td->legacy->inside_call) td->legacy->delete_me = EINA_TRUE;
|
2017-11-08 22:59:04 -08:00
|
|
|
else efl_del(timer);
|
2016-05-04 13:37:39 -07:00
|
|
|
return data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static void
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_timer_interval_set(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer, double in)
|
2005-02-22 04:39:50 -08:00
|
|
|
{
|
2012-09-18 04:47:22 -07:00
|
|
|
if (in < 0.0) in = 0.0;
|
2005-02-22 04:39:50 -08:00
|
|
|
timer->in = in;
|
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static double
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_timer_interval_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
|
2009-04-26 10:16:33 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
return timer->in;
|
2009-04-26 10:16:33 -07:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static void
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_timer_delay(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *pd, double add)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_util_delay(pd, add);
|
2008-04-11 16:39:55 -07:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static void
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_timer_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
|
2011-12-04 15:12:06 -08:00
|
|
|
{
|
|
|
|
double now, add;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!timer->loop_data) return;
|
2017-02-07 16:32:22 -08:00
|
|
|
// Do not reset the current timer while inside the callback
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->loop_data->timer_current == timer) return;
|
2017-02-07 16:32:22 -08:00
|
|
|
|
2011-12-04 15:12:06 -08:00
|
|
|
now = ecore_time_get();
|
2016-05-04 13:37:39 -07:00
|
|
|
if (!timer->initialized)
|
|
|
|
{
|
|
|
|
timer->at = now;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->frozen) add = timer->pending;
|
|
|
|
else add = timer->at - now;
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_util_delay(timer, timer->in - add);
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_timer_loop_reset(Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
|
2016-05-04 13:37:39 -07:00
|
|
|
{
|
|
|
|
double now, add;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!timer->loop_data) return;
|
2017-02-07 16:32:22 -08:00
|
|
|
// Do not reset the current timer while inside the callback
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->loop_data->timer_current == timer) return;
|
2017-02-07 16:32:22 -08:00
|
|
|
|
2017-12-26 08:40:07 -08:00
|
|
|
now = efl_loop_time_get(timer->loop);
|
2016-05-04 13:37:39 -07:00
|
|
|
if (!timer->initialized)
|
|
|
|
{
|
|
|
|
timer->at = now;
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2016-05-04 13:37:39 -07:00
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->frozen) add = timer->pending;
|
|
|
|
else add = timer->at - now;
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_util_delay(timer, timer->in - add);
|
2011-12-04 15:12:06 -08:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static double
|
2019-03-08 07:33:05 -08:00
|
|
|
_efl_loop_timer_time_pending_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
double now, ret = 0.0;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2008-04-11 16:39:55 -07:00
|
|
|
now = ecore_time_get();
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->frozen) ret = timer->pending;
|
|
|
|
else ret = timer->at - now;
|
2014-03-23 22:47:52 -07:00
|
|
|
return ret;
|
2008-04-11 16:39:55 -07:00
|
|
|
}
|
2014-03-23 22:47:52 -07:00
|
|
|
|
2008-03-09 08:56:17 -07:00
|
|
|
EAPI void
|
|
|
|
ecore_timer_freeze(Ecore_Timer *timer)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
|
|
|
ECORE_TIMER_CHECK(timer);
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_event_freeze(timer);
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_efl_object_event_freeze(Eo *obj, Efl_Loop_Timer_Data *timer)
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
2019-05-29 06:14:56 -07:00
|
|
|
double now = 0.0;
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_event_freeze(efl_super(obj, MY_CLASS));
|
2017-11-08 22:59:04 -08:00
|
|
|
// Timer already frozen
|
|
|
|
if (timer->frozen) return;
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2019-05-29 06:14:56 -07:00
|
|
|
/* not set if timer is not finalized */
|
|
|
|
if (timer->loop)
|
|
|
|
now = efl_loop_time_get(timer->loop);
|
2018-08-26 20:09:49 -07:00
|
|
|
/* only if timer interval has been set */
|
|
|
|
if (timer->initialized)
|
|
|
|
timer->pending = timer->at - now;
|
|
|
|
else
|
|
|
|
timer->pending = 0.0;
|
2008-03-09 08:56:17 -07:00
|
|
|
timer->at = 0.0;
|
|
|
|
timer->frozen = 1;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
|
|
|
|
2013-11-09 23:51:42 -08:00
|
|
|
EAPI Eina_Bool
|
|
|
|
ecore_timer_freeze_get(Ecore_Timer *timer)
|
|
|
|
{
|
2016-07-13 16:55:03 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
|
2017-11-08 22:59:04 -08:00
|
|
|
return !!efl_event_freeze_count_get(timer);
|
2013-11-09 23:51:42 -08:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static int
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_loop_timer_efl_object_event_freeze_count_get(const Eo *obj EINA_UNUSED, Efl_Loop_Timer_Data *timer)
|
2013-11-09 23:51:42 -08:00
|
|
|
{
|
2014-03-23 22:47:52 -07:00
|
|
|
return timer->frozen;
|
2013-11-09 23:51:42 -08:00
|
|
|
}
|
|
|
|
|
2008-03-09 08:56:17 -07:00
|
|
|
EAPI void
|
|
|
|
ecore_timer_thaw(Ecore_Timer *timer)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
|
|
|
ECORE_TIMER_CHECK(timer);
|
2016-08-10 07:23:04 -07:00
|
|
|
efl_event_thaw(timer);
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
|
|
|
|
2014-03-23 22:47:52 -07:00
|
|
|
EOLIAN static void
|
2016-08-10 07:23:04 -07:00
|
|
|
_efl_loop_timer_efl_object_event_thaw(Eo *obj, Efl_Loop_Timer_Data *timer)
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
|
|
|
double now;
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_event_thaw(efl_super(obj, MY_CLASS));
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!timer->frozen) return; // Timer not frozen
|
2018-08-26 20:09:49 -07:00
|
|
|
timer->frozen = 0;
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (timer->loop_data)
|
|
|
|
{
|
|
|
|
timer->loop_data->suspended = eina_inlist_remove
|
|
|
|
(timer->loop_data->suspended, EINA_INLIST_GET(timer));
|
|
|
|
}
|
2008-03-09 08:56:17 -07:00
|
|
|
now = ecore_time_get();
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_set(timer, timer->pending + now, timer->in);
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
|
|
|
|
2011-05-17 10:32:32 -07:00
|
|
|
EAPI char *
|
|
|
|
ecore_timer_dump(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
static void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_loop_clear(Efl_Loop_Timer_Data *pd)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
Eina_Inlist *first;
|
2011-07-28 05:01:16 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!pd->loop_data) return;
|
|
|
|
// Check if we are the current timer, if so move along
|
|
|
|
if (pd->loop_data->timer_current == pd)
|
|
|
|
pd->loop_data->timer_current = (Efl_Loop_Timer_Data *)
|
|
|
|
EINA_INLIST_GET(pd)->next;
|
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
// Remove the timer from all possible pending list
|
2017-11-08 22:59:04 -08:00
|
|
|
first = eina_inlist_first(EINA_INLIST_GET(pd));
|
|
|
|
if (first == pd->loop_data->timers)
|
|
|
|
pd->loop_data->timers = eina_inlist_remove
|
|
|
|
(pd->loop_data->timers, EINA_INLIST_GET(pd));
|
|
|
|
else if (first == pd->loop_data->suspended)
|
|
|
|
pd->loop_data->suspended = eina_inlist_remove
|
|
|
|
(pd->loop_data->suspended, EINA_INLIST_GET(pd));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_efl_loop_timer_util_instanciate(Efl_Loop_Data *loop, Efl_Loop_Timer_Data *timer)
|
|
|
|
{
|
|
|
|
Efl_Loop_Timer_Data *t2;
|
|
|
|
|
|
|
|
if (!loop) return;
|
|
|
|
_efl_loop_timer_util_loop_clear(timer);
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
// And start putting it back where it belong
|
2017-11-08 22:59:04 -08:00
|
|
|
if ((!timer->listening) || (timer->frozen) ||
|
|
|
|
(timer->at <= 0.0) || (timer->in < 0.0))
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
loop->suspended = eina_inlist_prepend(loop->suspended,
|
|
|
|
EINA_INLIST_GET(timer));
|
|
|
|
return;
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-02-02 16:52:10 -08:00
|
|
|
if (!timer->initialized)
|
|
|
|
{
|
2017-12-13 09:53:33 -08:00
|
|
|
ERR("Trying to instantiate an uninitialized timer is impossible.");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2017-02-02 16:52:10 -08:00
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
EINA_INLIST_REVERSE_FOREACH(loop->timers, t2)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
if (timer->at > t2->at)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
loop->timers = eina_inlist_append_relative(loop->timers,
|
|
|
|
EINA_INLIST_GET(timer),
|
|
|
|
EINA_INLIST_GET(t2));
|
2016-05-04 13:37:39 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
loop->timers = eina_inlist_prepend(loop->timers, EINA_INLIST_GET(timer));
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
static void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_delay(Efl_Loop_Timer_Data *timer, double add)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2017-02-02 16:52:10 -08:00
|
|
|
if (!timer->initialized)
|
|
|
|
{
|
|
|
|
ERR("Impossible to delay an uninitialized timer.");
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2017-02-02 16:52:10 -08:00
|
|
|
}
|
2016-05-04 13:37:39 -07:00
|
|
|
if (timer->frozen)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
timer->pending += add;
|
2017-11-08 22:59:04 -08:00
|
|
|
return;
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_set(timer, timer->at + add, timer->in);
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
|
|
|
|
2016-06-06 14:59:06 -07:00
|
|
|
EOLIAN static void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_efl_object_parent_set(Eo *obj, Efl_Loop_Timer_Data *pd, Efl_Object *parent)
|
2016-06-06 14:59:06 -07:00
|
|
|
{
|
2018-08-02 06:14:15 -07:00
|
|
|
Eina_Inlist *first;
|
|
|
|
|
2017-12-13 14:49:57 -08:00
|
|
|
efl_parent_set(efl_super(obj, EFL_LOOP_TIMER_CLASS), parent);
|
2016-06-06 14:59:06 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if ((!pd->constructed) || (!pd->finalized)) return;
|
2016-06-06 14:59:06 -07:00
|
|
|
|
2018-08-02 06:14:15 -07:00
|
|
|
// Remove the timer from all possible pending list
|
|
|
|
first = eina_inlist_first(EINA_INLIST_GET(pd));
|
|
|
|
if (first == pd->loop_data->timers)
|
2019-10-24 08:22:49 -07:00
|
|
|
{
|
|
|
|
/* if this timer is currently being processed, update the pointer here so it is not lost */
|
|
|
|
if (pd == pd->loop_data->timer_current)
|
|
|
|
pd->loop_data->timer_current = (Efl_Loop_Timer_Data*)EINA_INLIST_GET(pd)->next;
|
|
|
|
pd->loop_data->timers = eina_inlist_remove(pd->loop_data->timers, EINA_INLIST_GET(pd));
|
|
|
|
}
|
2018-08-02 06:14:15 -07:00
|
|
|
else if (first == pd->loop_data->suspended)
|
|
|
|
pd->loop_data->suspended = eina_inlist_remove
|
|
|
|
(pd->loop_data->suspended, EINA_INLIST_GET(pd));
|
2016-06-06 14:59:06 -07:00
|
|
|
|
2018-03-08 15:18:38 -08:00
|
|
|
if (efl_invalidated_get(obj)) return;
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
2017-12-27 08:19:52 -08:00
|
|
|
if (pd->loop)
|
|
|
|
pd->loop_data = efl_data_scope_get(pd->loop, EFL_LOOP_CLASS);
|
|
|
|
else
|
|
|
|
pd->loop_data = NULL;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (efl_parent_get(obj) != parent) return;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_instanciate(pd->loop_data, pd);
|
2015-05-20 06:56:45 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (parent != NULL) pd->noparent = EINA_FALSE;
|
|
|
|
else pd->noparent = EINA_TRUE;
|
2015-05-20 06:56:45 -07:00
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
EOLIAN static void
|
|
|
|
_efl_loop_timer_efl_object_destructor(Eo *obj, Efl_Loop_Timer_Data *pd)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_loop_clear(pd);
|
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_enable_new(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!pd->timers_added) return;
|
|
|
|
pd->timers_added = 0;
|
|
|
|
EINA_INLIST_FOREACH(pd->timers, timer) timer->just_added = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
Fix the bug of the first timer being added from idler.
We should start doing unit-test for ecore, accumulating these
problems. Follows the test case:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static int quiter(void *data)
{
INF("quit!");
ecore_main_loop_quit();
return 1;
}
static int idler(void *data)
{
INF("idler");
return 1;
}
static int cb1(void *data)
{
INF("cb1");
ecore_timer_add(0.0, quiter, NULL);
return 0;
}
int main(void)
{
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Create a main loop with just idlers, there is a special case
* for just idlers without timers in ecore.
*
* From idler, add a timer that quits the application. It should
* always quit.
*
* If it does not quit, then there is a bug of new timers not
* being immediately detected and system never exits idle.
*/
INF("main: begin");
ecore_idler_add(cb1, NULL);
ecore_idler_add(idler, NULL);
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46405
2010-02-23 13:04:38 -08:00
|
|
|
int
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timers_exists(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
|
Fix the bug of the first timer being added from idler.
We should start doing unit-test for ecore, accumulating these
problems. Follows the test case:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static int quiter(void *data)
{
INF("quit!");
ecore_main_loop_quit();
return 1;
}
static int idler(void *data)
{
INF("idler");
return 1;
}
static int cb1(void *data)
{
INF("cb1");
ecore_timer_add(0.0, quiter, NULL);
return 0;
}
int main(void)
{
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Create a main loop with just idlers, there is a special case
* for just idlers without timers in ecore.
*
* From idler, add a timer that quits the application. It should
* always quit.
*
* If it does not quit, then there is a bug of new timers not
* being immediately detected and system never exits idle.
*/
INF("main: begin");
ecore_idler_add(cb1, NULL);
ecore_idler_add(idler, NULL);
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46405
2010-02-23 13:04:38 -08:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
return !!pd->timers;
|
Fix the bug of the first timer being added from idler.
We should start doing unit-test for ecore, accumulating these
problems. Follows the test case:
#include <Ecore.h>
#include <Eina.h>
static int _log_dom;
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
static int quiter(void *data)
{
INF("quit!");
ecore_main_loop_quit();
return 1;
}
static int idler(void *data)
{
INF("idler");
return 1;
}
static int cb1(void *data)
{
INF("cb1");
ecore_timer_add(0.0, quiter, NULL);
return 0;
}
int main(void)
{
ecore_init();
_log_dom = eina_log_domain_register("test", EINA_COLOR_CYAN);
/*
* Create a main loop with just idlers, there is a special case
* for just idlers without timers in ecore.
*
* From idler, add a timer that quits the application. It should
* always quit.
*
* If it does not quit, then there is a bug of new timers not
* being immediately detected and system never exits idle.
*/
INF("main: begin");
ecore_idler_add(cb1, NULL);
ecore_idler_add(idler, NULL);
ecore_main_loop_begin();
INF("main: end");
return 0;
}
SVN revision: 46405
2010-02-23 13:04:38 -08:00
|
|
|
}
|
|
|
|
|
2008-11-13 12:42:01 -08:00
|
|
|
static inline Ecore_Timer *
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_first_get(Eo *ob EINA_UNUSED, Efl_Loop_Data *pd)
|
2008-11-13 12:42:01 -08:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
EINA_INLIST_FOREACH(pd->timers, timer)
|
|
|
|
{
|
|
|
|
if (!timer->just_added) return timer->object;
|
|
|
|
}
|
2016-05-04 13:37:39 -07:00
|
|
|
return NULL;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
|
2016-06-03 16:01:08 -07:00
|
|
|
static inline Efl_Loop_Timer_Data *
|
|
|
|
_efl_loop_timer_after_get(Efl_Loop_Timer_Data *base)
|
2008-11-13 12:42:01 -08:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer;
|
|
|
|
Efl_Loop_Timer_Data *valid_timer = base;
|
2008-11-13 12:42:01 -08:00
|
|
|
double maxtime = base->at + precision;
|
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
EINA_INLIST_FOREACH(EINA_INLIST_GET(base)->next, timer)
|
2011-07-26 00:01:55 -07:00
|
|
|
{
|
2017-02-02 16:52:10 -08:00
|
|
|
if (EINA_UNLIKELY(!timer->initialized)) continue; // This shouldn't happen
|
2016-05-04 13:37:39 -07:00
|
|
|
if (timer->at >= maxtime) break;
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!timer->just_added) valid_timer = timer;
|
2011-07-26 00:01:55 -07:00
|
|
|
}
|
2016-05-04 13:37:39 -07:00
|
|
|
return valid_timer;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
double
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_next_get(Eo *obj, Efl_Loop_Data *pd)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2016-05-04 13:37:39 -07:00
|
|
|
Ecore_Timer *object;
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *first;
|
2003-09-23 01:09:32 -07:00
|
|
|
double now;
|
|
|
|
double in;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
object = _efl_loop_timer_first_get(obj, pd);
|
2016-05-04 13:37:39 -07:00
|
|
|
if (!object) return -1;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
first = _efl_loop_timer_after_get(efl_data_scope_get(object, MY_CLASS));
|
2017-12-26 08:40:07 -08:00
|
|
|
now = efl_loop_time_get(obj);
|
2008-11-13 12:42:01 -08:00
|
|
|
in = first->at - now;
|
2003-09-23 01:09:32 -07:00
|
|
|
if (in < 0) in = 0;
|
|
|
|
return in;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
static inline void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_reschedule(Efl_Loop_Timer_Data *timer, double when)
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
{
|
2019-10-28 11:59:11 -07:00
|
|
|
if (timer->frozen || efl_invalidated_get(timer->object) ||
|
|
|
|
(timer->legacy && timer->legacy->delete_me)) return;
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
|
2018-03-08 17:00:03 -08:00
|
|
|
if (timer->loop_data &&
|
|
|
|
(EINA_INLIST_GET(timer)->next || EINA_INLIST_GET(timer)->prev))
|
2017-11-08 22:59:04 -08:00
|
|
|
{
|
|
|
|
if (timer->loop_data->timers && (!timer->noparent))
|
|
|
|
timer->loop_data->timers = eina_inlist_remove
|
|
|
|
(timer->loop_data->timers, EINA_INLIST_GET(timer));
|
|
|
|
}
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
|
|
|
|
/* if the timer would have gone off more than 15 seconds ago,
|
|
|
|
* assume that the system hung and set the timer to go off
|
|
|
|
* timer->in from now. this handles system hangs, suspends
|
|
|
|
* and more, so ecore will only "replay" the timers while
|
|
|
|
* the system is suspended if it is suspended for less than
|
|
|
|
* 15 seconds (basically). this also handles if the process
|
|
|
|
* is stopped in a debugger or IO and other handling gets
|
|
|
|
* really slow within the main loop.
|
|
|
|
*/
|
|
|
|
if ((timer->at + timer->in) < (when - 15.0))
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_set(timer, when + timer->in, timer->in);
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
else
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_set(timer, timer->at + timer->in, timer->in);
|
Reschedule timer_current in case of inner mainloop
Timers' list is and *ordered list*. Therefore, timers can be added
before timer_current in an inner mainloop. Reschedule timer_current in
this case before looping through timers' list.
Thanks to Barbieri for the insight.
The following test didn't work before and it's ok now (I'm adding it to
ecore_suite too).
static int _timer3(void *data)
{
printf("timer 3, do nothing\n");
return 0;
}
static int _timer2(void *data)
{
printf("timer 2, quit inner\n");
ecore_main_loop_quit();
return 0;
}
static int _timer1(void *data)
{
int *times = data;
(*times)++;
printf("BEGIN: inner\n");
ecore_timer_add(0.3, _timer2, NULL);
ecore_timer_add(0.1, _timer3, NULL);
ecore_main_loop_begin();
printf("END: inner\n");
ecore_main_loop_quit();
return 0;
}
int main(void)
{
int times = 0;
ecore_init();
ecore_timer_add(1.0, _timer1, ×);
printf("BEGIN: main\n");
ecore_main_loop_begin();
assert(times == 1);
printf("timer1 called %d times \n", times);
printf("END: main\n");
return 0;
}
By: Lucas De Marchi <lucas.demarchi@profusion.mobi>
SVN revision: 49245
2010-05-27 19:31:02 -07:00
|
|
|
}
|
|
|
|
|
2011-09-01 20:29:11 -07:00
|
|
|
void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_expired_timers_call(Eo *obj, Efl_Loop_Data *pd, double when)
|
2011-09-01 20:29:11 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// call the first expired timer until no expired timers exist
|
|
|
|
while (_efl_loop_timer_expired_call(obj, pd, when));
|
2011-09-01 20:29:11 -07:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
int
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_expired_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, double when)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!pd->timers) return 0;
|
|
|
|
if (pd->last_check > when)
|
2005-04-04 09:01:39 -07:00
|
|
|
{
|
2016-06-03 16:01:08 -07:00
|
|
|
Efl_Loop_Timer_Data *timer;
|
2017-11-08 22:59:04 -08:00
|
|
|
// User set time backwards
|
|
|
|
EINA_INLIST_FOREACH(pd->timers, timer)
|
|
|
|
timer->at -= (pd->last_check - when);
|
2005-04-04 09:01:39 -07:00
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->last_check = when;
|
2010-02-23 16:27:04 -08:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!pd->timer_current) // regular main loop, start from head
|
|
|
|
pd->timer_current = (Efl_Loop_Timer_Data *)pd->timers;
|
2010-02-23 16:27:04 -08:00
|
|
|
else
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
// recursive main loop, continue from where we were
|
|
|
|
Efl_Loop_Timer_Data *timer_old = pd->timer_current;
|
2016-05-04 13:37:39 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->timer_current = (Efl_Loop_Timer_Data *)
|
|
|
|
EINA_INLIST_GET(pd->timer_current)->next;
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_reschedule(timer_old, when);
|
2010-02-23 16:27:04 -08:00
|
|
|
}
|
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
while (pd->timer_current)
|
2010-02-23 16:27:04 -08:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
Efl_Loop_Timer_Data *timer = pd->timer_current;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
|
|
|
if (timer->at > when)
|
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->timer_current = NULL; // ended walk, next should restart.
|
2010-09-29 23:09:20 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-05-04 13:37:39 -07:00
|
|
|
if (timer->just_added)
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
pd->timer_current = (Efl_Loop_Timer_Data *)
|
|
|
|
EINA_INLIST_GET(pd->timer_current)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_ref(timer->object);
|
2015-05-10 03:05:54 -07:00
|
|
|
eina_evlog("+timer", timer, 0.0, NULL);
|
2019-10-24 08:22:49 -07:00
|
|
|
/* this can remove timer from its inlist in the legacy codepath */
|
2019-03-08 07:33:05 -08:00
|
|
|
efl_event_callback_call(timer->object, EFL_LOOP_TIMER_EVENT_TIMER_TICK, NULL);
|
2015-05-10 03:05:54 -07:00
|
|
|
eina_evlog("-timer", timer, 0.0, NULL);
|
2010-09-29 23:09:20 -07:00
|
|
|
|
2017-11-08 22:59:04 -08:00
|
|
|
// may have changed in recursive main loops
|
|
|
|
// this current timer can not die yet as we hold a reference on it
|
2019-10-24 08:22:49 -07:00
|
|
|
/* this is tricky: the current timer cannot be deleted, but it CAN be removed from its inlist,
|
|
|
|
* thus breaking timer processing
|
|
|
|
*/
|
2017-11-08 22:59:04 -08:00
|
|
|
if (pd->timer_current)
|
2019-10-24 08:22:49 -07:00
|
|
|
{
|
|
|
|
if (pd->timer_current == timer)
|
|
|
|
pd->timer_current = (Efl_Loop_Timer_Data *)EINA_INLIST_GET(pd->timer_current)->next;
|
|
|
|
/* assume this has otherwise been modified either due to recursive mainloop processing or
|
|
|
|
* the timer being removed from its inlist and carefully updating pd->timer_current in the
|
|
|
|
* process as only the most elite of engineers would think to do
|
|
|
|
*/
|
|
|
|
}
|
2016-06-03 16:01:08 -07:00
|
|
|
_efl_loop_timer_reschedule(timer, when);
|
2016-08-15 06:44:41 -07:00
|
|
|
efl_unref(timer->object);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
return 0;
|
2008-11-29 03:23:17 -08:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
static void
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_set(Efl_Loop_Timer_Data *timer, double at, double in)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2017-11-08 22:59:04 -08:00
|
|
|
if (!timer->loop_data) return;
|
|
|
|
timer->loop_data->timers_added = 1;
|
2003-09-23 01:09:32 -07:00
|
|
|
timer->in = in;
|
|
|
|
timer->just_added = 1;
|
2016-05-04 13:37:39 -07:00
|
|
|
timer->initialized = 1;
|
2018-08-26 20:09:49 -07:00
|
|
|
if (!timer->frozen)
|
|
|
|
{
|
|
|
|
timer->at = at;
|
|
|
|
timer->pending = 0.0;
|
|
|
|
}
|
2017-11-08 22:59:04 -08:00
|
|
|
_efl_loop_timer_util_instanciate(timer->loop_data, timer);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2016-06-03 16:01:08 -07:00
|
|
|
#include "efl_loop_timer.eo.c"
|
2019-03-05 14:00:37 -08:00
|
|
|
#include "efl_loop_timer_eo.legacy.c"
|