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);
}
#define ECORE_CALLBACK_RENEW
Return value to keep a callback.
Definition: Ecore_Common.h:153
double ecore_time_get(void)
Retrieves the current system time as a floating point value in seconds.
Definition: ecore_time.c:33
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)
{
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();
EAPI int ecore_init(void)
Sets up connections, signal handlers, sockets etc.
Definition: ecore.c:230
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
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
#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:

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));
void ecore_main_loop_begin(void)
Runs the application main loop.
Definition: ecore_main.c:1311
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 * 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
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_interval_set(poller2, 16, NULL);
// efl_unref(poller1);
// efl_unref(poller2);
// efl_unref(poller3);
ecore_poller_del(poller1);
ecore_poller_del(poller2);
ecore_poller_del(poller3);
}
EAPI int ecore_shutdown(void)
Shuts down connections, signal handlers sockets etc.
Definition: ecore.c:371
void * ecore_poller_del(Ecore_Poller *poller)
Deletes the specified poller from the timer list.
Definition: ecore_poller.c:332
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.