ecore poller - Repetitive polling tasks

This example shows how to setup, and explains how an Ecore_Poller is called. You can see the full source code here.

In this example we store the initial time of the program just to use as comparison to the time when the poller callbacks are called. It will be stored in `_initial_time` :

//Compile with:
// gcc -o ecore_poller_example ecore_poller_example.c `pkg-config --libs --cflags ecore eo`
#include <Ecore.h>
//#include <Ecore_Eo.h>
#include <unistd.h>
static double _initial_time = 0;

Then next step is to define the poller callback. This callback assumes that a `data` pointer is passed to it on creation, and is a string just used to identify the poller. The callback prints this string and the time since the program started, and returns ECORE_CALLBACK_RENEW to keep being called.

static Eina_Bool
_poller_print_cb(void *data)
{
char *str = data;
printf("Ecore Poller '%s' callback called after %0.3f seconds.\n",
str, ecore_time_get() - _initial_time);
return ECORE_CALLBACK_RENEW;
}
ECORE_CALLBACK_RENEW
#define ECORE_CALLBACK_RENEW
Return value to keep a callback.
Definition Ecore_Common.h:153
ecore_time_get
double ecore_time_get(void)
Retrieves the current system time as a floating point value in seconds.
Definition ecore_time.c:33
Eina_Bool
unsigned char Eina_Bool
Type to mimic a boolean.
Definition eina_types.h:527

Now in the main function we initialize Ecore, and save the initial time of the program, so we can compare it later with the time that the pollers are being called:

static Eina_Bool
_poller_quit_cb(void *data EINA_UNUSED)
{
ecore_main_loop_quit();
return EINA_TRUE;
}
int
main(void)
{
double interval = 0.3; // tick each 0.3 seconds
Ecore_Poller *poller1, *poller2, *poller3;
char *str1 = "poller1";
char *str2 = "poller2";
char *str3 = "poller3";
if (!ecore_init())
{
printf("ERROR: Cannot init Ecore!\n");
return -1;
}
_initial_time = ecore_time_get();
ecore_init
EAPI int ecore_init(void)
Sets up connections, signal handlers, sockets etc.
Definition ecore.c:230
ecore_main_loop_quit
void ecore_main_loop_quit(void)
Quits the main loop once all the events currently on the queue have been processed.
Definition ecore_main.c:1321
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition eina_types.h:539
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition eina_types.h:339

Then we change the poll interval to 0.3 seconds (the default is 0.125 seconds) just to show the API usage.

Finally, we create two pollers, one that will be called every 4 ticks, and another one that will be called every 8 ticks. This means the the first poller interval will be around 1.2 seconds, and the second one will be around 2.4 seconds. But the most important point is: since the second poller interval is a multiple of the first one, they will be always synchronized. Ecore calls pollers that are in the "same tick" together. It doesn't go back to the main loop and check if there's another poller to execute at this time, but instead it calls all the pollers registered to this "tick" at the same time. See the description of ecore_poller_add() for more details. This is easy to see in the time printed by both of them.

If instead of two synchronized pollers, we were using two different timers, one with interval of 1.2 seconds and another one with an interval of 2.4 seconds, there would be no guarantee that they would be totally in sync. Some delay in the execution of another task, or even in the task called in the callback, could make them get out of sync, forcing Ecore's main loop to wake up more than necessary.

Well, this is the code that create these two pollers and set the poll interval, then starts the main loop:

ecore_poller_poll_interval_set(ECORE_POLLER_CORE, interval);
poller1 = ecore_poller_add(ECORE_POLLER_CORE, 4, _poller_print_cb, str1);
poller2 = ecore_poller_add(ECORE_POLLER_CORE, 8, _poller_print_cb, str2);
poller3 = ecore_poller_add(ECORE_POLLER_CORE, 30, _poller_quit_cb, str3);
// poller1 = efl_add_ref(ECORE_POLLER_CLASS, NULL, // ecore_poller_constructor(efl_added, ECORE_POLLER_CORE, 4, _poller_print_cb, str1));
// poller2 = efl_add_ref(ECORE_POLLER_CLASS, NULL, // ecore_poller_constructor(efl_added, ECORE_POLLER_CORE, 8, _poller_print_cb, str2));
// poller3 = efl_add_ref(ECORE_POLLER_CLASS, NULL, // ecore_poller_constructor(efl_added, ECORE_POLLER_CORE, 20, _poller_quit_cb, str3));
ecore_main_loop_begin();
ecore_main_loop_begin
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition ecore_main.c:1311
ecore_poller_poll_interval_set
void ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time)
Sets the time(in seconds) between ticks for the given poller type.
Definition ecore_poller.c:215
ecore_poller_add
Ecore_Poller * ecore_poller_add(Ecore_Poller_Type type, int interval, Ecore_Task_Cb func, const void *data)
Creates a poller to call the given function at a particular tick interval.
Definition ecore_poller.c:238
ECORE_POLLER_CORE
@ ECORE_POLLER_CORE
The core poller interval.
Definition Ecore_Legacy.h:11

If you hit CTRL-C during the execution of the program, the main loop will quit, since there are some signal handlers already set by default to do this. So after the main loop begin call, we change the second poller's interval to 16 ticks, so it will happen each 4.8 seconds (or each 4 times that the first poller is called).

This means: the program is started, the first poller is called each 4 ticks and the second is called each 8 ticks. After CTRL-C is used, the second poller will be called each 16 ticks.

printf("changing poller2 interval to 16\n");
ecore_poller_poller_interval_set(poller2, 16);
// ecore_poller_interval_set(poller2, 16, NULL);
ecore_main_loop_begin();
// efl_unref(poller1);
// efl_unref(poller2);
// efl_unref(poller3);
ecore_poller_del(poller1);
ecore_poller_del(poller2);
ecore_poller_del(poller3);
ecore_shutdown();
}
ecore_shutdown
EAPI int ecore_shutdown(void)
Shuts down connections, signal handlers sockets etc.
Definition ecore.c:371
ecore_poller_del
void * ecore_poller_del(Ecore_Poller *poller)
Deletes the specified poller from the timer list.
Definition ecore_poller.c:332
ecore_poller_poller_interval_set
Eina_Bool ecore_poller_poller_interval_set(Ecore_Poller *obj, int interval)
Polling interval rate of the poller.
Definition ecore_poller.c:282

The rest of the program is just deleting the pollers and shutting down the library.