2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2012-11-18 22:26:48 -08:00
|
|
|
#include <Eo.h>
|
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
#include "Ecore.h"
|
2009-12-22 13:15:12 -08:00
|
|
|
#include "ecore_private.h"
|
2008-01-10 23:33:57 -08:00
|
|
|
|
2012-10-10 01:19:58 -07:00
|
|
|
#define MY_CLASS ECORE_POLLER_CLASS
|
|
|
|
|
2013-11-07 03:16:01 -08:00
|
|
|
#define MY_CLASS_NAME "Ecore_Poller"
|
2012-10-10 01:19:58 -07:00
|
|
|
|
|
|
|
#define ECORE_POLLER_CHECK(obj) \
|
2016-08-15 06:44:41 -07:00
|
|
|
if (!efl_isa((obj), ECORE_POLLER_CLASS)) \
|
2012-10-10 01:19:58 -07:00
|
|
|
return
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
struct _Ecore_Poller
|
2011-12-11 00:29:35 -08:00
|
|
|
{
|
|
|
|
EINA_INLIST;
|
2012-04-05 21:14:25 -07:00
|
|
|
ECORE_MAGIC;
|
2011-12-11 00:29:35 -08:00
|
|
|
int ibit;
|
|
|
|
unsigned char delete_me : 1;
|
|
|
|
Ecore_Task_Cb func;
|
|
|
|
void *data;
|
|
|
|
};
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static Ecore_Timer *timer = NULL;
|
|
|
|
static int min_interval = -1;
|
|
|
|
static int interval_incr = 0;
|
|
|
|
static int at_tick = 0;
|
|
|
|
static int just_added_poller = 0;
|
|
|
|
static int poller_delete_count = 0;
|
|
|
|
static int poller_walking = 0;
|
|
|
|
static double poll_interval = 0.125;
|
|
|
|
static double poll_cur_interval = 0.0;
|
|
|
|
static double last_tick = 0.0;
|
2017-06-02 15:38:25 -07:00
|
|
|
static Ecore_Poller *pollers[16] =
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
2008-01-10 23:33:57 -08:00
|
|
|
};
|
2011-10-20 22:40:39 -07:00
|
|
|
static unsigned short poller_counters[16] =
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
2008-01-10 23:33:57 -08:00
|
|
|
};
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
static void _ecore_poller_next_tick_eval(void);
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool _ecore_poller_cb_timer(void *data);
|
2008-01-10 23:33:57 -08:00
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
static void *
|
|
|
|
_ecore_poller_cleanup(Ecore_Poller *poller)
|
|
|
|
{
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
data = poller->data;
|
|
|
|
pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
|
|
|
|
|
|
|
|
free(poller);
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
static void
|
|
|
|
_ecore_poller_next_tick_eval(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
double interval;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
min_interval = -1;
|
|
|
|
for (i = 0; i < 15; i++)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
if (pollers[i])
|
|
|
|
{
|
|
|
|
min_interval = i;
|
|
|
|
break;
|
|
|
|
}
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
if (min_interval < 0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* no pollers */
|
2011-10-20 22:40:39 -07:00
|
|
|
if (timer)
|
|
|
|
{
|
|
|
|
ecore_timer_del(timer);
|
|
|
|
timer = NULL;
|
|
|
|
}
|
|
|
|
return;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
interval_incr = (1 << min_interval);
|
|
|
|
interval = interval_incr * poll_interval;
|
|
|
|
/* we are at the tick callback - so no need to do inter-tick adjustments
|
|
|
|
* so we can fasttrack this as t -= last_tick in theory is 0.0 (though
|
|
|
|
* in practice it will be a very very very small value. also the tick
|
|
|
|
* callback will adjust the timer interval at the end anyway */
|
|
|
|
if (at_tick)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
if (!timer)
|
|
|
|
timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
double t;
|
|
|
|
|
|
|
|
if (!timer)
|
|
|
|
timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
|
|
|
|
else
|
|
|
|
{
|
2017-02-03 11:12:28 -08:00
|
|
|
t = ecore_loop_time_get();
|
2017-03-21 11:11:19 -07:00
|
|
|
if (!EINA_DBL_EQ(interval, poll_cur_interval))
|
2010-09-29 23:09:20 -07:00
|
|
|
{
|
|
|
|
t -= last_tick; /* time since we last ticked */
|
2011-10-20 22:40:39 -07:00
|
|
|
/* delete the timer and reset it to tick off in the new
|
|
|
|
* time interval. at the tick this will be adjusted */
|
2010-09-29 23:09:20 -07:00
|
|
|
ecore_timer_del(timer);
|
2017-02-03 11:12:28 -08:00
|
|
|
timer = ecore_timer_loop_add(interval - t,
|
|
|
|
_ecore_poller_cb_timer, NULL);
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
}
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
poll_cur_interval = interval;
|
|
|
|
}
|
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2012-11-25 01:55:32 -08:00
|
|
|
_ecore_poller_cb_timer(void *data EINA_UNUSED)
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
2017-06-02 15:38:25 -07:00
|
|
|
Ecore_Poller *poller;
|
2008-01-10 23:33:57 -08:00
|
|
|
int i;
|
|
|
|
int changes = 0;
|
|
|
|
|
|
|
|
at_tick++;
|
2017-02-03 11:12:28 -08:00
|
|
|
last_tick = ecore_loop_time_get();
|
2012-01-03 16:11:55 -08:00
|
|
|
/* we have 16 counters - each increments every time the poller counter
|
|
|
|
* "ticks". it increments by the minimum interval (which can be 1, 2, 4,
|
2008-01-10 23:33:57 -08:00
|
|
|
* 7, 16 etc. up to 32768) */
|
|
|
|
for (i = 0; i < 15; i++)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
poller_counters[i] += interval_incr;
|
|
|
|
/* wrap back to 0 if we exceed out loop count for the counter */
|
|
|
|
if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
just_added_poller = 0;
|
|
|
|
/* walk the pollers now */
|
|
|
|
poller_walking++;
|
|
|
|
for (i = 0; i < 15; i++)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* if the counter is @ 0 - this means that counter "went off" this
|
|
|
|
* tick interval, so run all pollers hooked to that counter */
|
2011-10-20 22:40:39 -07:00
|
|
|
if (poller_counters[i] == 0)
|
|
|
|
{
|
|
|
|
EINA_INLIST_FOREACH(pollers[i], poller)
|
|
|
|
{
|
|
|
|
if (!poller->delete_me)
|
|
|
|
{
|
|
|
|
if (!poller->func(poller->data))
|
|
|
|
{
|
|
|
|
if (!poller->delete_me)
|
|
|
|
{
|
|
|
|
poller->delete_me = 1;
|
|
|
|
poller_delete_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
poller_walking--;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
/* handle deletes afterwards */
|
|
|
|
if (poller_delete_count > 0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
/* FIXME: walk all pollers and remove deleted ones */
|
2011-10-20 22:40:39 -07:00
|
|
|
for (i = 0; i < 15; i++)
|
|
|
|
{
|
2017-06-02 15:38:25 -07:00
|
|
|
Eina_Inlist *l;
|
|
|
|
|
|
|
|
EINA_INLIST_FOREACH_SAFE(pollers[i], l, poller)
|
2011-10-20 22:40:39 -07:00
|
|
|
{
|
|
|
|
if (poller->delete_me)
|
|
|
|
{
|
2017-06-02 15:38:25 -07:00
|
|
|
_ecore_poller_cleanup(poller);
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
poller_delete_count--;
|
|
|
|
changes++;
|
|
|
|
if (poller_delete_count <= 0) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (poller_delete_count <= 0) break;
|
|
|
|
}
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
/* if we deleted or added any pollers, then we need to re-evaluate our
|
|
|
|
* minimum poll interval */
|
|
|
|
if ((changes > 0) || (just_added_poller > 0))
|
|
|
|
_ecore_poller_next_tick_eval();
|
|
|
|
|
|
|
|
just_added_poller = 0;
|
|
|
|
poller_delete_count = 0;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
at_tick--;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
/* if the timer was deleted then there is no point returning 1 - ambiguous
|
2012-01-03 16:11:55 -08:00
|
|
|
* if we do as it implies keep running me" but we have been deleted
|
2008-01-10 23:33:57 -08:00
|
|
|
* anyway */
|
2010-06-24 09:15:56 -07:00
|
|
|
if (!timer) return ECORE_CALLBACK_CANCEL;
|
2008-01-10 23:33:57 -08:00
|
|
|
|
|
|
|
/* adjust interval */
|
|
|
|
ecore_timer_interval_set(timer, poll_cur_interval);
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void
|
2012-11-25 01:55:32 -08:00
|
|
|
ecore_poller_poll_interval_set(Ecore_Poller_Type type EINA_UNUSED,
|
2011-10-20 22:40:39 -07:00
|
|
|
double poll_time)
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN;
|
2012-09-18 04:38:08 -07:00
|
|
|
|
|
|
|
if (poll_time < 0.0)
|
|
|
|
{
|
|
|
|
ERR("Poll time %f less than zero, ignored", poll_time);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
poll_interval = poll_time;
|
|
|
|
_ecore_poller_next_tick_eval();
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI double
|
2012-11-25 01:55:32 -08:00
|
|
|
ecore_poller_poll_interval_get(Ecore_Poller_Type type EINA_UNUSED)
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
2012-03-29 01:52:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(0.0);
|
2008-01-10 23:33:57 -08:00
|
|
|
return poll_interval;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Ecore_Poller *
|
2012-11-25 01:55:32 -08:00
|
|
|
ecore_poller_add(Ecore_Poller_Type type EINA_UNUSED,
|
2011-10-20 22:40:39 -07:00
|
|
|
int interval,
|
|
|
|
Ecore_Task_Cb func,
|
|
|
|
const void *data)
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
|
|
|
Ecore_Poller *poller;
|
|
|
|
int ibit;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
poller = calloc(1, sizeof (Ecore_Poller));
|
|
|
|
if (!poller) return NULL;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2018-10-26 03:25:09 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2012-10-10 01:19:58 -07:00
|
|
|
|
|
|
|
if (!func)
|
|
|
|
{
|
|
|
|
ERR("callback function must be set up for an object of class: '%s'", MY_CLASS_NAME);
|
2017-07-12 07:58:28 -07:00
|
|
|
free(poller);
|
2017-06-02 15:38:25 -07:00
|
|
|
return NULL;
|
2012-10-10 01:19:58 -07:00
|
|
|
}
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
/* interval MUST be a power of 2, so enforce it */
|
|
|
|
if (interval < 1) interval = 1;
|
|
|
|
ibit = -1;
|
|
|
|
while (interval != 0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
ibit++;
|
|
|
|
interval >>= 1;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
/* only allow up to 32768 - i.e. ibit == 15, so limit it */
|
|
|
|
if (ibit > 15) ibit = 15;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
poller->ibit = ibit;
|
|
|
|
poller->func = func;
|
|
|
|
poller->data = (void *)data;
|
2017-06-02 15:38:25 -07:00
|
|
|
pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
|
2008-01-10 23:33:57 -08:00
|
|
|
if (poller_walking)
|
|
|
|
just_added_poller++;
|
|
|
|
else
|
|
|
|
_ecore_poller_next_tick_eval();
|
2017-06-02 15:38:25 -07:00
|
|
|
|
|
|
|
return poller;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
ecore_poller_poller_interval_set(Ecore_Poller *poller, int interval)
|
2012-10-10 01:19:58 -07:00
|
|
|
{
|
2010-05-19 02:16:37 -07:00
|
|
|
int ibit;
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
if (!poller) return EINA_FALSE;
|
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
|
|
|
|
|
2010-05-19 02:16:37 -07:00
|
|
|
/* interval MUST be a power of 2, so enforce it */
|
|
|
|
if (interval < 1) interval = 1;
|
|
|
|
ibit = -1;
|
|
|
|
while (interval != 0)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
ibit++;
|
|
|
|
interval >>= 1;
|
2010-05-19 02:16:37 -07:00
|
|
|
}
|
|
|
|
/* only allow up to 32768 - i.e. ibit == 15, so limit it */
|
|
|
|
if (ibit > 15) ibit = 15;
|
|
|
|
/* if interval specified is the same as interval set, return true without wasting time */
|
2014-03-23 06:32:06 -07:00
|
|
|
if (poller->ibit == ibit) return EINA_TRUE;
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_remove(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
|
2010-05-19 02:16:37 -07:00
|
|
|
poller->ibit = ibit;
|
2017-06-02 15:38:25 -07:00
|
|
|
pollers[poller->ibit] = (Ecore_Poller *)eina_inlist_prepend(EINA_INLIST_GET(pollers[poller->ibit]), EINA_INLIST_GET(poller));
|
2010-05-19 02:16:37 -07:00
|
|
|
if (poller_walking)
|
|
|
|
just_added_poller++;
|
|
|
|
else
|
|
|
|
_ecore_poller_next_tick_eval();
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2014-03-23 06:32:06 -07:00
|
|
|
return EINA_TRUE;
|
2010-05-19 02:16:37 -07:00
|
|
|
}
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
EAPI int
|
|
|
|
ecore_poller_poller_interval_get(const Ecore_Poller *poller)
|
2010-05-19 02:16:37 -07:00
|
|
|
{
|
|
|
|
int ibit, interval = 1;
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
if (!poller) return -1;
|
2014-04-17 12:08:43 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(interval);
|
2010-05-19 02:16:37 -07:00
|
|
|
|
|
|
|
ibit = poller->ibit;
|
|
|
|
while (ibit != 0)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
ibit--;
|
|
|
|
interval <<= 1;
|
2010-05-19 02:16:37 -07:00
|
|
|
}
|
2017-06-02 15:38:25 -07:00
|
|
|
|
2014-03-23 06:32:06 -07:00
|
|
|
return interval;
|
2010-05-19 02:16:37 -07:00
|
|
|
}
|
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
EAPI void *
|
2017-06-02 15:38:25 -07:00
|
|
|
ecore_poller_del(Ecore_Poller *poller)
|
2008-01-10 23:33:57 -08:00
|
|
|
{
|
|
|
|
void *data;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2016-08-31 19:16:12 -07:00
|
|
|
if (!poller) return NULL;
|
2017-06-02 15:38:25 -07:00
|
|
|
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
2008-01-10 23:33:57 -08:00
|
|
|
/* we are walking the poller list - a bad idea to remove from it while
|
|
|
|
* walking it, so just flag it as delete_me and come back to it after
|
|
|
|
* the loop has finished */
|
|
|
|
if (poller_walking > 0)
|
|
|
|
{
|
2010-05-19 02:16:37 -07:00
|
|
|
poller_delete_count++;
|
|
|
|
poller->delete_me = 1;
|
|
|
|
return poller->data;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
|
|
|
/* not in loop so safe - delete immediately */
|
2017-06-02 15:38:25 -07:00
|
|
|
data = _ecore_poller_cleanup(poller);
|
2012-10-10 01:19:58 -07:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
_ecore_poller_next_tick_eval();
|
|
|
|
|
2017-06-02 15:38:25 -07:00
|
|
|
return data;
|
2015-05-20 06:56:45 -07:00
|
|
|
}
|
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
void
|
|
|
|
_ecore_poller_shutdown(void)
|
|
|
|
{
|
2017-06-02 15:38:25 -07:00
|
|
|
Ecore_Poller *poller;
|
2008-01-10 23:33:57 -08:00
|
|
|
int i;
|
2008-11-29 03:23:17 -08:00
|
|
|
|
2008-01-10 23:33:57 -08:00
|
|
|
for (i = 0; i < 15; i++)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
while ((poller = pollers[i]))
|
2017-06-02 15:38:25 -07:00
|
|
|
_ecore_poller_cleanup(poller);
|
2017-12-18 20:44:33 -08:00
|
|
|
poller_counters[i] = 0;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|
2017-12-18 20:44:33 -08:00
|
|
|
|
|
|
|
if (timer)
|
|
|
|
{
|
|
|
|
ecore_timer_del(timer);
|
|
|
|
timer = NULL;
|
|
|
|
}
|
|
|
|
min_interval = -1;
|
|
|
|
interval_incr = 0;
|
|
|
|
at_tick = 0;
|
|
|
|
just_added_poller = 0;
|
|
|
|
poller_delete_count = 0;
|
|
|
|
poller_walking = 0;
|
|
|
|
poll_interval = 0.125;
|
|
|
|
poll_cur_interval = 0.0;
|
|
|
|
last_tick = 0.0;
|
2008-01-10 23:33:57 -08:00
|
|
|
}
|