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
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
#define MY_CLASS ECORE_TIMER_CLASS
|
|
|
|
#define MY_CLASS_NAME "ecore_timer"
|
|
|
|
|
|
|
|
EAPI Eo_Op ECORE_TIMER_BASE_ID = EO_NOOP;
|
|
|
|
|
|
|
|
#define ECORE_TIMER_CHECK(obj) \
|
|
|
|
if (!eo_isa((obj), ECORE_TIMER_CLASS)) \
|
|
|
|
return
|
|
|
|
|
2011-12-11 00:29:35 -08:00
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
|
|
|
# include <string.h>
|
|
|
|
# include <execinfo.h>
|
|
|
|
# define ECORE_TIMER_DEBUG_BT_NUM 64
|
|
|
|
typedef void (*Ecore_Timer_Bt_Func)();
|
|
|
|
#endif
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
struct _Ecore_Timer_Private_Data
|
2011-12-11 00:29:35 -08:00
|
|
|
{
|
|
|
|
EINA_INLIST;
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer *obj;
|
2011-12-11 00:29:35 -08:00
|
|
|
double in;
|
|
|
|
double at;
|
|
|
|
double pending;
|
|
|
|
Ecore_Task_Cb func;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
|
|
|
Ecore_Timer_Bt_Func timer_bt[ECORE_TIMER_DEBUG_BT_NUM];
|
|
|
|
int timer_bt_num;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int references;
|
|
|
|
unsigned char delete_me : 1;
|
|
|
|
unsigned char just_added : 1;
|
|
|
|
unsigned char frozen : 1;
|
|
|
|
};
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
typedef struct _Ecore_Timer_Private_Data Ecore_Timer_Private_Data;
|
|
|
|
|
|
|
|
static void _ecore_timer_set(Ecore_Timer *timer,
|
2011-10-20 22:40:39 -07:00
|
|
|
double at,
|
|
|
|
double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
void *data);
|
2011-11-14 14:33:34 -08:00
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
2011-10-20 22:40:39 -07:00
|
|
|
static int _ecore_timer_cmp(const void *d1,
|
|
|
|
const void *d2);
|
2011-11-14 14:33:34 -08:00
|
|
|
#endif
|
2010-01-03 13:55:50 -08:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static int timers_added = 0;
|
|
|
|
static int timers_delete_me = 0;
|
2012-10-10 01:19:58 -07:00
|
|
|
static Ecore_Timer_Private_Data *timers = NULL;
|
|
|
|
static Ecore_Timer_Private_Data *timer_current = NULL;
|
|
|
|
static Ecore_Timer_Private_Data *suspended = NULL;
|
2011-10-20 22:40:39 -07:00
|
|
|
static double last_check = 0.0;
|
|
|
|
static double precision = 10.0 / 1000000.0;
|
2010-10-17 00:03:28 -07:00
|
|
|
|
|
|
|
/**
|
2012-03-09 11:21:47 -08:00
|
|
|
* @addtogroup Ecore_Timer_Group
|
2011-06-21 10:15:54 -07:00
|
|
|
*
|
2010-10-17 00:03:28 -07:00
|
|
|
* @{
|
2004-09-22 21:58:16 -07:00
|
|
|
*/
|
|
|
|
|
2008-11-13 12:42:01 -08:00
|
|
|
/**
|
|
|
|
* Retrieves the current precision used by timer infrastructure.
|
2012-04-05 00:00:42 -07:00
|
|
|
* @return Current precision.
|
2008-11-13 12:42:01 -08:00
|
|
|
* @see ecore_timer_precision_set()
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-03-09 11:21:52 -08:00
|
|
|
* @brief Sets the precision to be used by timer infrastructure.
|
2008-11-13 12:42:01 -08:00
|
|
|
*
|
2012-03-09 11:21:52 -08:00
|
|
|
* @param value allowed introduced timeout delay, in seconds.
|
|
|
|
*
|
|
|
|
* This sets the precision for @b all timers. The precision determines how much
|
|
|
|
* of an difference from the requested interval is acceptable. One common reason
|
|
|
|
* to use this function is to @b increase the allowed timeout and thus @b
|
|
|
|
* decrease precision of the timers, this is because less precise the timers
|
|
|
|
* result in the system waking up less often and thus consuming less resources.
|
2008-11-13 12:42:01 -08:00
|
|
|
*
|
|
|
|
* Be aware that kernel may delay delivery even further, these delays
|
|
|
|
* are always possible due other tasks having higher priorities or
|
|
|
|
* other scheduler policies.
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* We have 2 timers, one that expires in a 2.0s and another that
|
|
|
|
* expires in 2.1s, if precision is 0.1s, then the Ecore will request
|
|
|
|
* for the next expire to happen in 2.1s and not 2.0s and another one
|
|
|
|
* of 0.1 as it would before.
|
|
|
|
*
|
|
|
|
* @note Ecore is smart enough to see if there are timers in the
|
|
|
|
* precision range, if it does not, in our example if no second timer
|
|
|
|
* in (T + precision) existed, then it would use the minimum timeout.
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
ecore_timer_precision_set(double value)
|
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2008-11-13 12:42:01 -08:00
|
|
|
if (value < 0.0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ERR("Precision %f less than zero, ignored", value);
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
precision = value;
|
2011-07-28 05:01:16 -07:00
|
|
|
|
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
|
2004-09-22 21:58:16 -07:00
|
|
|
/**
|
|
|
|
* Creates a timer to call the given function in the given period of time.
|
|
|
|
* @param in The interval in seconds.
|
|
|
|
* @param func The given function. If @p func returns 1, the timer is
|
|
|
|
* rescheduled for the next interval @p in.
|
|
|
|
* @param data Data to pass to @p func when it is called.
|
|
|
|
* @return A timer object on success. @c NULL on failure.
|
2006-12-27 19:31:44 -08:00
|
|
|
*
|
|
|
|
* This function adds a timer and returns its handle on success and NULL on
|
2009-03-13 02:38:46 -07:00
|
|
|
* failure. The function @p func will be called every @p in seconds. The
|
2006-12-27 19:31:44 -08:00
|
|
|
* function will be passed the @p data pointer as its parameter.
|
2008-11-29 03:23:17 -08:00
|
|
|
*
|
|
|
|
* When the timer @p func is called, it must return a value of either 1
|
|
|
|
* (or ECORE_CALLBACK_RENEW) or 0 (or ECORE_CALLBACK_CANCEL).
|
2006-12-27 19:31:44 -08:00
|
|
|
* If it returns 1, it will be called again at the next tick, or if it returns
|
|
|
|
* 0 it will be deleted automatically making any references/handles for it
|
|
|
|
* invalid.
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Timer *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_timer_add(double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
const void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
Ecore_Timer *timer = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2012-10-10 01:19:58 -07:00
|
|
|
timer = eo_add_custom(MY_CLASS, _ecore_parent, ecore_timer_constructor(in, func, data));
|
|
|
|
eo_unref(timer);
|
|
|
|
return timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_ecore_timer_add(Ecore_Timer *obj,
|
|
|
|
Ecore_Timer_Private_Data *timer,
|
|
|
|
double now,
|
|
|
|
double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
const void *data)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (EINA_UNLIKELY(!eina_main_loop_is()))
|
|
|
|
{
|
|
|
|
eo_error_set(obj);
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
timer->obj = obj;
|
|
|
|
eo_do_super(obj, eo_constructor());
|
|
|
|
eo_manual_free_set(obj, EINA_TRUE);
|
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
eo_error_set(obj);
|
|
|
|
ERR("callback function must be set up for an object of class: '%s'", MY_CLASS_NAME);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
if (in < 0.0) in = 0.0;
|
2011-05-17 10:32:32 -07:00
|
|
|
|
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
2011-10-20 22:40:39 -07:00
|
|
|
timer->timer_bt_num = backtrace((void **)(timer->timer_bt),
|
2011-05-17 10:32:32 -07:00
|
|
|
ECORE_TIMER_DEBUG_BT_NUM);
|
|
|
|
#endif
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_set(obj, now + in, in, func, (void *)data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
static void
|
|
|
|
_timer_constructor(Eo *obj, void *_pd, va_list *list)
|
|
|
|
{
|
|
|
|
double in = va_arg(*list, double);
|
|
|
|
Ecore_Task_Cb func = va_arg(*list, Ecore_Task_Cb);
|
|
|
|
const void *data = va_arg(*list, const void *);
|
|
|
|
double now;
|
|
|
|
|
|
|
|
_ecore_lock();
|
|
|
|
now = ecore_time_get();
|
|
|
|
|
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
_ecore_timer_add(obj, timer, now, in, func, data);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
static void
|
|
|
|
_timer_loop_constructor(Eo *obj, void *_pd, va_list *list)
|
|
|
|
{
|
|
|
|
double in = va_arg(*list, double);
|
|
|
|
Ecore_Task_Cb func = va_arg(*list, Ecore_Task_Cb);
|
|
|
|
const void *data = va_arg(*list, const void *);
|
|
|
|
double now;
|
|
|
|
|
|
|
|
now = ecore_loop_time_get();
|
|
|
|
|
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
_ecore_timer_add(obj, timer, now, in, func, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_constructor(Eo *obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
|
|
|
|
{
|
|
|
|
eo_error_set(obj);
|
|
|
|
ERR("only custom constructor can be used with '%s' class", MY_CLASS_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-22 19:13:50 -07:00
|
|
|
/**
|
|
|
|
* Creates a timer to call the given function in the given period of time.
|
|
|
|
* @param in The interval in seconds from current loop time.
|
|
|
|
* @param func The given function. If @p func returns 1, the timer is
|
|
|
|
* rescheduled for the next interval @p in.
|
|
|
|
* @param data Data to pass to @p func when it is called.
|
|
|
|
* @return A timer object on success. @c NULL on failure.
|
|
|
|
*
|
|
|
|
* This is the same as ecore_timer_add(), but "now" is the time from
|
|
|
|
* ecore_loop_time_get() not ecore_time_get() as ecore_timer_add() uses. See
|
|
|
|
* ecore_timer_add() for more details.
|
|
|
|
*/
|
|
|
|
EAPI Ecore_Timer *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_timer_loop_add(double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
const void *data)
|
2009-03-22 19:13:50 -07:00
|
|
|
{
|
|
|
|
Ecore_Timer *timer;
|
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
|
|
|
timer = _ecore_timer_loop_add(in, func, data);
|
|
|
|
_ecore_unlock();
|
2011-05-19 08:38:30 -07:00
|
|
|
|
2009-03-22 19:13:50 -07:00
|
|
|
return timer;
|
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/**
|
|
|
|
* Delete the specified timer from the timer list.
|
2004-09-22 21:58:16 -07:00
|
|
|
* @param timer The timer to delete.
|
|
|
|
* @return The data pointer set for the timer when @ref ecore_timer_add was
|
|
|
|
* called. @c NULL is returned if the function is unsuccessful.
|
2006-12-27 19:31:44 -08:00
|
|
|
*
|
|
|
|
* Note: @p timer must be a valid handle. If the timer function has already
|
|
|
|
* returned 0, the handle is no longer valid (and does not need to be delete).
|
2003-09-23 01:09:32 -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)
|
|
|
|
{
|
2011-07-28 05:01:16 -07:00
|
|
|
void *data = NULL;
|
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
data = _ecore_timer_del(timer);
|
2009-11-13 08:57:12 -08:00
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
|
|
|
return data;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2005-02-22 04:39:50 -08:00
|
|
|
/**
|
|
|
|
* Change the interval the timer ticks of. If set during
|
|
|
|
* a timer call, this will affect the next interval.
|
|
|
|
*
|
|
|
|
* @param timer The timer to change.
|
|
|
|
* @param in The interval in seconds.
|
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_timer_interval_set(Ecore_Timer *timer,
|
|
|
|
double in)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
|
|
|
ECORE_TIMER_CHECK(timer);
|
|
|
|
eo_do(timer, ecore_obj_timer_interval_set(in));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_interval_set(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
|
2005-02-22 04:39:50 -08:00
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2012-10-10 01:19:58 -07:00
|
|
|
double in = va_arg(*list, double);
|
2012-09-18 04:47:22 -07:00
|
|
|
if (in < 0.0) in = 0.0;
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
|
|
|
|
_ecore_lock();
|
2005-02-22 04:39:50 -08:00
|
|
|
timer->in = in;
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2005-02-22 04:39:50 -08:00
|
|
|
}
|
|
|
|
|
2009-04-26 10:16:33 -07:00
|
|
|
/**
|
|
|
|
* Get the interval the timer ticks on.
|
|
|
|
*
|
|
|
|
* @param timer The timer to retrieve the interval from
|
|
|
|
* @return The interval on success. -1 on failure.
|
|
|
|
*/
|
|
|
|
EAPI double
|
|
|
|
ecore_timer_interval_get(Ecore_Timer *timer)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
double interval = -1.0;
|
2011-07-28 05:01:16 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
ECORE_TIMER_CHECK(timer) interval;
|
|
|
|
eo_do(timer, ecore_obj_timer_interval_get(&interval));
|
|
|
|
return interval;
|
|
|
|
}
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
static void
|
|
|
|
_timer_interval_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
|
|
|
|
{
|
|
|
|
double *ret = va_arg(*list, double *);
|
|
|
|
*ret = -1.0;
|
2009-04-26 10:16:33 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
_ecore_lock();
|
|
|
|
*ret = timer->in;
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2009-04-26 10:16:33 -07:00
|
|
|
}
|
|
|
|
|
2008-03-09 08:56:17 -07:00
|
|
|
/**
|
2010-09-08 04:23:42 -07:00
|
|
|
* Add some delay for the next occurrence of a timer.
|
2008-04-11 16:39:55 -07:00
|
|
|
* This doesn't affect the interval of a timer.
|
|
|
|
*
|
|
|
|
* @param timer The timer to change.
|
2012-07-28 02:24:18 -07:00
|
|
|
* @param add The delay to add to the next iteration.
|
2008-04-11 16:39:55 -07:00
|
|
|
*/
|
|
|
|
EAPI void
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_timer_delay(Ecore_Timer *timer,
|
|
|
|
double add)
|
2008-04-11 16:39:55 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
ECORE_TIMER_CHECK(timer);
|
|
|
|
eo_do(timer, ecore_obj_timer_delay(add));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_delay(Eo *obj, void *_pd EINA_UNUSED, va_list *list)
|
|
|
|
{
|
|
|
|
double add = va_arg(*list, double);
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2008-04-11 16:39:55 -07:00
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_delay(obj, add);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2008-04-11 16:39:55 -07:00
|
|
|
}
|
|
|
|
|
2011-12-04 15:12:06 -08:00
|
|
|
/**
|
|
|
|
* Reset a timer to its full interval
|
|
|
|
* This doesn't affect the interval of a timer
|
|
|
|
* @param timer The timer
|
|
|
|
* @since 1.2
|
|
|
|
* @note This is equivalent to (but faster than)
|
|
|
|
* @code
|
|
|
|
* ecore_timer_delay(timer, ecore_timer_interval_get(timer) - ecore_timer_pending_get(timer));
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
EAPI void
|
|
|
|
ecore_timer_reset(Ecore_Timer *timer)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
|
|
|
ECORE_TIMER_CHECK(timer);
|
|
|
|
eo_do(timer, ecore_obj_timer_reset());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_reset(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
2011-12-04 15:12:06 -08:00
|
|
|
{
|
|
|
|
double now, add;
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
|
2011-12-04 15:12:06 -08:00
|
|
|
_ecore_lock();
|
|
|
|
now = ecore_time_get();
|
|
|
|
|
|
|
|
if (timer->frozen)
|
|
|
|
add = timer->pending;
|
|
|
|
else
|
|
|
|
add = timer->at - now;
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_delay(obj, timer->in - add);
|
2011-12-04 15:12:06 -08:00
|
|
|
_ecore_unlock();
|
|
|
|
}
|
|
|
|
|
2008-04-11 16:39:55 -07:00
|
|
|
/**
|
|
|
|
* Get the pending time regarding a timer.
|
|
|
|
*
|
2010-09-29 23:09:20 -07:00
|
|
|
* @param timer The timer to learn from.
|
2012-04-05 00:00:42 -07:00
|
|
|
* @return The pending time.
|
2012-03-09 11:21:47 -08:00
|
|
|
* @ingroup Ecore_Timer_Group
|
2008-04-11 16:39:55 -07:00
|
|
|
*/
|
|
|
|
EAPI double
|
|
|
|
ecore_timer_pending_get(Ecore_Timer *timer)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
double ret = 0.0;
|
2008-04-11 16:39:55 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
ECORE_TIMER_CHECK(timer) ret;
|
|
|
|
eo_do(timer, ecore_obj_timer_pending_get(&ret));
|
|
|
|
return ret;
|
|
|
|
}
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
static void
|
|
|
|
_timer_pending_get(Eo *obj EINA_UNUSED, void *_pd, va_list *list)
|
|
|
|
{
|
|
|
|
double now;
|
|
|
|
double *ret = va_arg(*list, double *);
|
|
|
|
*ret = 0.0;
|
|
|
|
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
|
|
|
|
|
|
|
_ecore_lock();
|
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
2008-04-11 16:39:55 -07:00
|
|
|
|
|
|
|
now = ecore_time_get();
|
|
|
|
|
|
|
|
if (timer->frozen)
|
2012-10-10 01:19:58 -07:00
|
|
|
*ret = timer->pending;
|
2011-07-28 05:01:16 -07:00
|
|
|
else
|
2012-10-10 01:19:58 -07:00
|
|
|
*ret = timer->at - now;
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2008-04-11 16:39:55 -07:00
|
|
|
}
|
|
|
|
/**
|
2011-06-29 11:15:36 -07:00
|
|
|
* Pauses a running timer.
|
2008-04-11 16:39:55 -07:00
|
|
|
*
|
2011-06-29 11:15:36 -07:00
|
|
|
* @param timer The timer to be paused.
|
2008-03-09 08:56:17 -07:00
|
|
|
*
|
2011-06-29 11:15:36 -07:00
|
|
|
* The timer callback won't be called while the timer is paused. The remaining
|
|
|
|
* time until the timer expires will be saved, so the timer can be resumed with
|
|
|
|
* that same remaining time to expire, instead of expiring instantly. Use
|
|
|
|
* ecore_timer_thaw() to resume it.
|
|
|
|
*
|
|
|
|
* @note Nothing happens if the timer was already paused.
|
|
|
|
*
|
|
|
|
* @see ecore_timer_thaw()
|
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);
|
|
|
|
eo_do(timer, eo_event_freeze());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_freeze(Eo *obj EINA_UNUSED, void *_pd, va_list *list EINA_UNUSED)
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
|
|
|
double now;
|
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
|
|
|
_ecore_lock();
|
2008-03-09 08:56:17 -07:00
|
|
|
|
|
|
|
/* Timer already frozen */
|
|
|
|
if (timer->frozen)
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
|
|
|
suspended = (Ecore_Timer_Private_Data *)eina_inlist_prepend(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
2008-03-09 08:56:17 -07:00
|
|
|
|
|
|
|
now = ecore_time_get();
|
|
|
|
|
|
|
|
timer->pending = timer->at - now;
|
|
|
|
timer->at = 0.0;
|
|
|
|
timer->frozen = 1;
|
2011-07-28 05:01:16 -07:00
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
|
|
|
|
2011-06-29 11:15:36 -07:00
|
|
|
/**
|
|
|
|
* Resumes a frozen (paused) timer.
|
|
|
|
*
|
|
|
|
* @param timer The timer to be resumed.
|
|
|
|
*
|
|
|
|
* The timer will be resumed from its previous relative position in time. That
|
|
|
|
* means, if it had X seconds remaining until expire when it was paused, it will
|
|
|
|
* be started now with those same X seconds remaining to expire again. But
|
|
|
|
* notice that the interval time won't be touched by this call or by
|
|
|
|
* ecore_timer_freeze().
|
|
|
|
*
|
|
|
|
* @see ecore_timer_freeze()
|
|
|
|
*/
|
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);
|
|
|
|
eo_do(timer, eo_event_thaw());
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_timer_thaw(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
|
|
|
double now;
|
|
|
|
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = _pd;
|
2011-07-05 04:13:29 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_lock();
|
2008-03-09 08:56:17 -07:00
|
|
|
|
|
|
|
/* Timer not frozen */
|
|
|
|
if (!timer->frozen)
|
2011-07-28 05:01:16 -07:00
|
|
|
goto unlock;
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
suspended = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
2008-03-09 08:56:17 -07:00
|
|
|
now = ecore_time_get();
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_set(obj, timer->pending + now, timer->in, timer->func, timer->data);
|
2011-07-28 05:01:16 -07:00
|
|
|
unlock:
|
|
|
|
_ecore_unlock();
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
|
|
|
|
2011-05-17 10:32:32 -07:00
|
|
|
EAPI char *
|
|
|
|
ecore_timer_dump(void)
|
|
|
|
{
|
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
|
|
|
Eina_Strbuf *result;
|
|
|
|
char *out;
|
2012-12-06 18:32:11 -08:00
|
|
|
Ecore_Timer_Private_Data *tm;
|
2011-05-17 10:32:32 -07:00
|
|
|
Eina_List *tmp = NULL;
|
2011-05-19 08:38:30 -07:00
|
|
|
int living_timer = 0;
|
|
|
|
int unknow_timer = 0;
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2012-12-06 18:32:11 -08:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_lock();
|
2011-05-17 10:32:32 -07:00
|
|
|
result = eina_strbuf_new();
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH(timers, tm)
|
|
|
|
tmp = eina_list_sorted_insert(tmp, _ecore_timer_cmp, tm);
|
|
|
|
|
|
|
|
EINA_LIST_FREE(tmp, tm)
|
|
|
|
{
|
|
|
|
char **strings;
|
|
|
|
int j;
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
if (!tm->frozen && !tm->delete_me)
|
|
|
|
living_timer++;
|
2011-05-19 08:38:30 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
strings = backtrace_symbols((void **)tm->timer_bt, tm->timer_bt_num);
|
2011-05-19 08:38:30 -07:00
|
|
|
if (tm->timer_bt_num <= 0 || strings == NULL)
|
2011-10-20 22:40:39 -07:00
|
|
|
{
|
|
|
|
unknow_timer++;
|
|
|
|
continue;
|
|
|
|
}
|
2011-05-17 10:32:32 -07:00
|
|
|
|
|
|
|
eina_strbuf_append_printf(result, "*** timer: %f ***\n", tm->in);
|
|
|
|
if (tm->frozen)
|
|
|
|
eina_strbuf_append(result, "FROZEN\n");
|
|
|
|
if (tm->delete_me)
|
|
|
|
eina_strbuf_append(result, "DELETED\n");
|
2011-05-18 02:12:07 -07:00
|
|
|
for (j = 0; j < tm->timer_bt_num; j++)
|
2011-05-17 10:32:32 -07:00
|
|
|
eina_strbuf_append_printf(result, "%s\n", strings[j]);
|
|
|
|
|
|
|
|
free(strings);
|
|
|
|
}
|
|
|
|
|
2011-05-19 08:38:30 -07:00
|
|
|
eina_strbuf_append_printf(result, "\n***\nThere is %i living timer.\nWe did lost track of %i timers.\n", living_timer, unknow_timer);
|
|
|
|
|
2011-05-17 10:32:32 -07:00
|
|
|
out = eina_strbuf_string_steal(result);
|
|
|
|
eina_strbuf_free(result);
|
2011-07-28 05:01:16 -07:00
|
|
|
_ecore_unlock();
|
2011-05-17 10:32:32 -07:00
|
|
|
|
|
|
|
return out;
|
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-10-17 00:03:28 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
Ecore_Timer *
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_timer_loop_add(double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
const void *data)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
|
|
|
Ecore_Timer *timer = NULL;
|
2012-10-10 01:19:58 -07:00
|
|
|
timer = eo_add_custom(MY_CLASS, _ecore_parent, ecore_timer_loop_constructor(in, func, data));
|
|
|
|
eo_unref(timer);
|
2011-07-28 05:01:16 -07:00
|
|
|
|
|
|
|
return timer;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_delay(Ecore_Timer *obj,
|
2011-10-20 22:40:39 -07:00
|
|
|
double add)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = eo_data_get(obj, MY_CLASS);
|
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
if (timer->frozen)
|
|
|
|
{
|
|
|
|
timer->pending += add;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
|
|
|
_ecore_timer_set(obj, timer->at + add, timer->in, timer->func, timer->data);
|
2011-07-28 05:01:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_del(Ecore_Timer *obj)
|
2011-07-28 05:01:16 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = eo_data_get(obj, MY_CLASS);
|
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
if (timer->frozen && !timer->references)
|
|
|
|
{
|
|
|
|
void *data = timer->data;
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
suspended = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
2011-07-28 05:01:16 -07:00
|
|
|
|
|
|
|
if (timer->delete_me)
|
|
|
|
timers_delete_me--;
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
eo_parent_set(obj, NULL);
|
|
|
|
|
|
|
|
if (eo_destructed_is(obj))
|
|
|
|
eo_manual_free(obj);
|
|
|
|
else
|
|
|
|
eo_manual_free_set(obj, EINA_FALSE);
|
2011-07-28 05:01:16 -07:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(timer->delete_me, NULL);
|
|
|
|
timer->delete_me = 1;
|
|
|
|
timers_delete_me++;
|
|
|
|
return timer->data;
|
|
|
|
}
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
static void
|
|
|
|
_destructor(Eo *obj, void *_pd, va_list *list EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Ecore_Timer_Private_Data *pd = _pd;
|
|
|
|
|
|
|
|
if (!pd->delete_me)
|
|
|
|
{
|
|
|
|
pd->delete_me = 1;
|
|
|
|
timers_delete_me++;
|
|
|
|
}
|
|
|
|
|
|
|
|
eo_do_super(obj, eo_destructor());
|
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
void
|
|
|
|
_ecore_timer_shutdown(void)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2009-06-17 04:39:37 -07:00
|
|
|
while ((timer = timers))
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timers));
|
|
|
|
|
|
|
|
eo_parent_set(timer->obj, NULL);
|
|
|
|
if (eo_destructed_is(timer->obj))
|
|
|
|
eo_manual_free(timer->obj);
|
|
|
|
else
|
|
|
|
eo_manual_free_set(timer->obj, EINA_FALSE);
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2008-03-09 08:56:17 -07:00
|
|
|
|
2009-06-17 04:39:37 -07:00
|
|
|
while ((timer = suspended))
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
suspended = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(suspended));
|
|
|
|
|
|
|
|
eo_parent_set(timer->obj, NULL);
|
|
|
|
if (eo_destructed_is(timer->obj))
|
|
|
|
eo_manual_free(timer->obj);
|
|
|
|
else
|
|
|
|
eo_manual_free_set(timer->obj, EINA_FALSE);
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
2010-02-23 16:27:04 -08:00
|
|
|
|
|
|
|
timer_current = NULL;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_timer_cleanup(void)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *l;
|
2010-07-09 07:52:45 -07:00
|
|
|
int in_use = 0, todo = timers_delete_me, done = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
if (!timers_delete_me) return;
|
2011-10-20 22:40:39 -07:00
|
|
|
for (l = timers; l; )
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = l;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
l = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(l)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
if (timer->delete_me)
|
|
|
|
{
|
|
|
|
if (timer->references)
|
|
|
|
{
|
|
|
|
in_use++;
|
|
|
|
continue;
|
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
|
|
|
|
|
|
|
eo_parent_set(timer->obj, NULL);
|
|
|
|
if (eo_destructed_is(timer->obj))
|
|
|
|
eo_manual_free(timer->obj);
|
|
|
|
else
|
|
|
|
eo_manual_free_set(timer->obj, EINA_FALSE);
|
2010-09-29 23:09:20 -07:00
|
|
|
timers_delete_me--;
|
|
|
|
done++;
|
|
|
|
if (timers_delete_me == 0) return;
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
for (l = suspended; l; )
|
2008-03-09 08:56:17 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = l;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
l = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(l)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
if (timer->delete_me)
|
|
|
|
{
|
|
|
|
if (timer->references)
|
|
|
|
{
|
|
|
|
in_use++;
|
|
|
|
continue;
|
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
suspended = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(suspended), EINA_INLIST_GET(timer));
|
|
|
|
|
|
|
|
eo_parent_set(timer->obj, NULL);
|
|
|
|
if (eo_destructed_is(timer->obj))
|
|
|
|
eo_manual_free(timer->obj);
|
|
|
|
else
|
|
|
|
eo_manual_free_set(timer->obj, EINA_FALSE);
|
2010-09-29 23:09:20 -07:00
|
|
|
timers_delete_me--;
|
|
|
|
done++;
|
|
|
|
if (timers_delete_me == 0) return;
|
|
|
|
}
|
2008-03-09 08:56:17 -07:00
|
|
|
}
|
2010-02-23 16:27:04 -08:00
|
|
|
|
|
|
|
if ((!in_use) && (timers_delete_me))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ERR("%d timers to delete, but they were not found!"
|
|
|
|
"Stats: todo=%d, done=%d, pending=%d, in_use=%d. "
|
|
|
|
"reset counter.",
|
|
|
|
timers_delete_me, todo, done, todo - done, in_use);
|
|
|
|
timers_delete_me = 0;
|
2010-02-23 16:27:04 -08:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_timer_enable_new(void)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
if (!timers_added) return;
|
|
|
|
timers_added = 0;
|
2010-02-16 08:52:02 -08:00
|
|
|
EINA_INLIST_FOREACH(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
|
|
|
|
_ecore_timers_exists(void)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = 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
|
|
|
|
|
|
|
while ((timer) && (timer->delete_me))
|
2012-10-10 01:19:58 -07:00
|
|
|
timer = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer)->next;
|
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
|
|
|
|
|
|
|
return !!timer;
|
|
|
|
}
|
|
|
|
|
2008-11-13 12:42:01 -08:00
|
|
|
static inline Ecore_Timer *
|
|
|
|
_ecore_timer_first_get(void)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer *ret = NULL;
|
|
|
|
Ecore_Timer_Private_Data *timer = timers;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
|
|
|
while ((timer) && ((timer->delete_me) || (timer->just_added)))
|
2012-10-10 01:19:58 -07:00
|
|
|
timer = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer)->next;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
if (timer)
|
|
|
|
ret = timer->obj;
|
|
|
|
return ret;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline Ecore_Timer *
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_after_get(Ecore_Timer *obj)
|
2008-11-13 12:42:01 -08:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer *ret = NULL;
|
|
|
|
Ecore_Timer_Private_Data *base = eo_data_get(obj, MY_CLASS);
|
|
|
|
|
|
|
|
Ecore_Timer_Private_Data *timer = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(base)->next;
|
|
|
|
Ecore_Timer_Private_Data *valid_timer = NULL;
|
2008-11-13 12:42:01 -08:00
|
|
|
double maxtime = base->at + precision;
|
|
|
|
|
2011-07-26 00:01:55 -07:00
|
|
|
while ((timer) && (timer->at < maxtime))
|
|
|
|
{
|
|
|
|
if (!((timer->delete_me) || (timer->just_added)))
|
2011-10-20 22:40:39 -07:00
|
|
|
valid_timer = timer;
|
2012-10-10 01:19:58 -07:00
|
|
|
timer = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer)->next;
|
2011-07-26 00:01:55 -07:00
|
|
|
}
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
if (valid_timer)
|
|
|
|
ret = valid_timer->obj;
|
|
|
|
return ret;
|
2008-11-13 12:42:01 -08:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
double
|
|
|
|
_ecore_timer_next_get(void)
|
|
|
|
{
|
|
|
|
double now;
|
|
|
|
double in;
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer *first_obj, *second_obj;
|
|
|
|
Ecore_Timer_Private_Data *first;
|
|
|
|
|
|
|
|
first_obj = _ecore_timer_first_get();
|
|
|
|
if (!first_obj) return -1;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
second_obj = _ecore_timer_after_get(first_obj);
|
|
|
|
if (second_obj) first_obj = second_obj;
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
first = eo_data_get(first_obj, MY_CLASS);
|
2008-11-13 12:42:01 -08:00
|
|
|
|
2008-11-01 19:19:18 -07:00
|
|
|
now = ecore_loop_time_get();
|
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
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_reschedule(Ecore_Timer *obj,
|
2011-10-20 22:40:39 -07:00
|
|
|
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
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = eo_data_get(obj, MY_CLASS);
|
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 ((timer->delete_me) || (timer->frozen)) return;
|
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_remove(EINA_INLIST_GET(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))
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_set(obj, when + timer->in, timer->in, timer->func, timer->data);
|
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
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_set(obj, timer->at + timer->in, timer->in, timer->func, timer->data);
|
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
|
|
|
/* assume that we hold the ecore lock when entering this function */
|
|
|
|
void
|
|
|
|
_ecore_timer_expired_timers_call(double when)
|
|
|
|
{
|
|
|
|
/* call the first expired timer until no expired timers exist */
|
2011-10-20 22:40:39 -07:00
|
|
|
while (_ecore_timer_expired_call(when)) ;
|
2011-09-01 20:29:11 -07:00
|
|
|
}
|
|
|
|
|
2011-07-28 05:01:16 -07:00
|
|
|
/* assume that we hold the ecore lock when entering this function */
|
2003-09-23 01:09:32 -07:00
|
|
|
int
|
2011-09-01 20:29:11 -07:00
|
|
|
_ecore_timer_expired_call(double when)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
if (!timers) return 0;
|
2005-04-04 09:01:39 -07:00
|
|
|
if (last_check > when)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer;
|
2010-09-29 23:09:20 -07:00
|
|
|
/* User set time backwards */
|
|
|
|
EINA_INLIST_FOREACH(timers, timer) timer->at -= (last_check - when);
|
2005-04-04 09:01:39 -07:00
|
|
|
}
|
|
|
|
last_check = when;
|
2010-02-23 16:27:04 -08:00
|
|
|
|
|
|
|
if (!timer_current)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* regular main loop, start from head */
|
2012-10-10 01:19:58 -07:00
|
|
|
timer_current = timers;
|
2010-02-23 16:27:04 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* recursive main loop, continue from where we were */
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer_old = timer_current;
|
|
|
|
timer_current = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer_current)->next;
|
|
|
|
_ecore_timer_reschedule(timer_old->obj, when);
|
2010-02-23 16:27:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
while (timer_current)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *timer = timer_current;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
|
|
|
if (timer->at > when)
|
|
|
|
{
|
|
|
|
timer_current = NULL; /* ended walk, next should restart. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((timer->just_added) || (timer->delete_me))
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
timer_current = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer_current)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
timer->references++;
|
2011-08-11 03:59:48 -07:00
|
|
|
if (!_ecore_call_task_cb(timer->func, timer->data))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
if (!timer->delete_me) _ecore_timer_del(timer->obj);
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
timer->references--;
|
|
|
|
|
|
|
|
if (timer_current) /* may have changed in recursive main loops */
|
2012-10-10 01:19:58 -07:00
|
|
|
timer_current = (Ecore_Timer_Private_Data *)EINA_INLIST_GET(timer_current)->next;
|
2010-09-29 23:09:20 -07:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_reschedule(timer->obj, when);
|
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
|
2012-10-10 01:19:58 -07:00
|
|
|
_ecore_timer_set(Ecore_Timer *obj,
|
2011-10-20 22:40:39 -07:00
|
|
|
double at,
|
|
|
|
double in,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
void *data)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
Ecore_Timer_Private_Data *t2;
|
|
|
|
|
|
|
|
Ecore_Timer_Private_Data *timer = eo_data_get(obj, MY_CLASS);
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
timers_added = 1;
|
|
|
|
timer->at = at;
|
|
|
|
timer->in = in;
|
|
|
|
timer->func = func;
|
|
|
|
timer->data = data;
|
|
|
|
timer->just_added = 1;
|
2008-03-09 08:56:17 -07:00
|
|
|
timer->frozen = 0;
|
|
|
|
timer->pending = 0.0;
|
2003-09-23 01:09:32 -07:00
|
|
|
if (timers)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
EINA_INLIST_REVERSE_FOREACH(EINA_INLIST_GET(timers), t2)
|
|
|
|
{
|
|
|
|
if (timer->at > t2->at)
|
|
|
|
{
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_append_relative(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer), EINA_INLIST_GET(t2));
|
2010-09-29 23:09:20 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2012-10-10 01:19:58 -07:00
|
|
|
timers = (Ecore_Timer_Private_Data *)eina_inlist_prepend(EINA_INLIST_GET(timers), EINA_INLIST_GET(timer));
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2011-11-14 14:33:34 -08:00
|
|
|
#ifdef WANT_ECORE_TIMER_DUMP
|
2011-05-17 10:32:32 -07:00
|
|
|
static int
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_timer_cmp(const void *d1,
|
|
|
|
const void *d2)
|
2011-05-17 10:32:32 -07:00
|
|
|
{
|
2012-12-06 18:32:11 -08:00
|
|
|
const Ecore_Timer_Private_Data *t1 = d1;
|
|
|
|
const Ecore_Timer_Private_Data *t2 = d2;
|
2011-05-17 10:32:32 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
return (int)((t1->in - t2->in) * 100);
|
2011-05-17 10:32:32 -07:00
|
|
|
}
|
2011-11-14 14:33:34 -08:00
|
|
|
#endif
|
2012-10-10 01:19:58 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_class_constructor(Eo_Class *klass)
|
|
|
|
{
|
|
|
|
const Eo_Op_Func_Description func_desc[] = {
|
|
|
|
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
|
|
|
|
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
|
|
|
|
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_CONSTRUCTOR), _timer_constructor),
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_LOOP_CONSTRUCTOR), _timer_loop_constructor),
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_INTERVAL_SET), _timer_interval_set),
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_INTERVAL_GET), _timer_interval_get),
|
|
|
|
|
|
|
|
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_FREEZE), _timer_freeze),
|
|
|
|
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_EVENT_THAW), _timer_thaw),
|
|
|
|
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_DELAY), _timer_delay),
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_RESET), _timer_reset),
|
|
|
|
EO_OP_FUNC(ECORE_TIMER_ID(ECORE_TIMER_SUB_ID_PENDING_GET), _timer_pending_get),
|
|
|
|
EO_OP_FUNC_SENTINEL
|
|
|
|
};
|
|
|
|
|
|
|
|
eo_class_funcs_set(klass, func_desc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Eo_Op_Description op_desc[] = {
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_CONSTRUCTOR, "Creates a timer to call the given function in the given period of time."),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_LOOP_CONSTRUCTOR, "Creates a timer to call the given function in the given period of time."),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_INTERVAL_SET, "Change the interval the timer ticks of."),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_INTERVAL_GET, "Get the interval the timer ticks on."),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_DELAY, "Add some delay for the next occurrence of a timer."),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_RESET, "Reset a timer to its full interval"),
|
|
|
|
EO_OP_DESCRIPTION(ECORE_TIMER_SUB_ID_PENDING_GET, "Get the pending time regarding a timer."),
|
|
|
|
EO_OP_DESCRIPTION_SENTINEL
|
|
|
|
};
|
|
|
|
static const Eo_Class_Description class_desc = {
|
|
|
|
EO_VERSION,
|
|
|
|
MY_CLASS_NAME,
|
|
|
|
EO_CLASS_TYPE_REGULAR,
|
|
|
|
EO_CLASS_DESCRIPTION_OPS(&ECORE_TIMER_BASE_ID, op_desc, ECORE_TIMER_SUB_ID_LAST),
|
|
|
|
NULL,
|
|
|
|
sizeof(Ecore_Timer_Private_Data),
|
|
|
|
_class_constructor,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
EO_DEFINE_CLASS(ecore_timer_class_get, &class_desc, EO_BASE_CLASS, NULL)
|