ecore/idler - Improve documentation and add an example.

SVN revision: 60602
This commit is contained in:
Rafael Antognolli 2011-06-22 18:29:38 +00:00
parent def2382a91
commit d83f174929
6 changed files with 198 additions and 0 deletions

View File

@ -4,6 +4,7 @@
* Here is a page with some Ecore examples explained:
*
* @li @ref ecore_time_example_c
* @li @ref ecore_idler_example_c
*
*/
@ -37,6 +38,72 @@
* @include ecore_time_example.c
*/
/**
* @page ecore_idler_example_c ecore idle state - Idlers, enterers and exiters
*
* This example demonstrates how to manage the idle state of the main loop. Once
* a program knows that the main loop is going to enter in idle state, it could
* start doing some processing until getting out of this state.
*
* To exemplify this, we also add events and a timer to this program, so we can
* see the idle exiter callback being called before processing the event and/or
* timer, the event/timer callback being called (processed), then the idle
* enterer being called before entering in idle state again. Once in idle, the
* main loop keeps calling the idler callback continuously until a new event or
* timer is received.
*
* First, we declare a struct that will be used as context to be passed to
* every callback. It's not useful everywhere, since this example is very
* simple and doesn't do anything other than printing messages, but using this
* context will make it a little bit more real. Our context will be used to
* delete the timer, idler, idle enterer and exiter, and the event handler, and
* also to count how many times the idler was called.
*
* Then we start declaring callbacks for the idle enterer, idle exiter and the
* idler itself. Idle enterer and exiter callbacks just print a message saying
* that they were called, while the idler, in addition to printing a message
* too, also sends an event every 10 times that it is called, incrementing the
* context count variable. This event will be used to make the main loop exit
* the idle state and call the event callback.
*
* These callbacks return @ref ECORE_CALLBACK_RENEW, since we want them to keep
* being called every time the main loop changes to/from idle state. Otherwise,
* if we didn't want them to be called again, they should return @ref
* ECORE_CALLBACK_CANCEL.
*
* The next function declared is the event callback @c _event_handler_cb. It
* will check if the idler was called more than 100 times already @c
* (ctxt->count > 100), and will delete the idler, idle enterer and exiter, the
* timer (if it still exists), and request that the main loop stop running. Then
* it returns @ref ECORE_CALLBACK_CANCEL to indicate that the event handler
* shouldn't be called anymore (this will delete it). If the @c count is still
* smaller than 100, the event callback just returns @ref ECORE_CALLBACK_RENEW
* and will keep being called every time that this event type is called.
*
* Finally, we add a callback to the timer, that will just print a message when
* it is called, and this will happen only once (@ref ECORE_CALLBACK_CANCEL is
* being returned). This timer callback is just here to show that the main loop
* gets out of idle state when processing timers too.
*
* The @b main function is simple, just creates a new type of event that we will
* use to demonstrate the event handling together with the idle state, adds the
* callbacks that we declared so far, fill the context struct, and starts
* running the main loop.
*
* @note We use timer and event callbacks to demonstrate the idle state
* changing, but it also happens for file descriptor handlers, pipe handlers,
* etc.
*
* @include ecore_idler_example.c
*/
/**
* @example ecore_idler_example.c
* This example shows when @ref Ecore_Idler, @ref Ecore_Idle_Enterer and @ref
* Ecore_Idle_Exiter are called. See
* @ref ecore_idler_example_c "the explanation here".
*/
/**
* @example ecore_time_example.c
* Shows the difference between the three time functions. See @ref

View File

@ -12,6 +12,7 @@ LDADD = \
@dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ @rt_libs@ -lm
SRCS = \
ecore_idler_example.c \
ecore_time_example.c \
client_bench.c \
server_bench.c \
@ -31,6 +32,7 @@ endif
if EFL_BUILD_EXAMPLES
pkglib_PROGRAMS += \
ecore_idler_example \
ecore_time_example
endif

View File

@ -0,0 +1,113 @@
#include <Ecore.h>
#include <unistd.h>
struct context { // helper struct to give some context to the callbacks
int count;
Ecore_Idle_Enterer *enterer;
Ecore_Idler *idler;
Ecore_Idle_Exiter *exiter;
Ecore_Event_Handler *handler;
Ecore_Timer *timer;
};
static _event_type = 0; // a new type of event will be defined and stored here
static Eina_Bool
_enterer_cb(void *data) // the idle enterer callback
{
printf("IDLE ENTERER: Ecore entering in idle state.\n");
return ECORE_CALLBACK_RENEW; // same as EINA_TRUE
}
static Eina_Bool
_exiter_cb(void *data) // the idle exiter callback
{
printf("IDLE EXITER: Ecore exiting idle state.\n");
return ECORE_CALLBACK_RENEW; // same as EINA_TRUE
}
static Eina_Bool
_idler_cb(void *data) // the idler callback - ran while the mainloop is idle
{
struct context *ctxt = data;
printf("IDLER: executing idler callback while in idle state.\n");
ctxt->count++;
/* each 10 times that the callback gets called, generate an event that
* will wake up the main loop, triggering idle enterers, exiters, etc. */
if ((ctxt->count % 10) == 0)
ecore_event_add(_event_type, NULL, NULL, NULL);
return ECORE_CALLBACK_RENEW; // same as EINA_TRUE
}
static Eina_Bool
_event_handler_cb(void *data, int type, void *event) // event callback
{
struct context *ctxt = data;
printf("EVENT: processing callback for the event received.\n");
if (ctxt->count > 100)
{
ecore_idle_enterer_del(ctxt->enterer);
ecore_idle_exiter_del(ctxt->exiter);
ecore_idler_del(ctxt->idler);
ctxt->enterer = NULL;
ctxt->exiter = NULL;
ctxt->idler = NULL;
if (ctxt->timer)
{
ecore_timer_del(ctxt->timer);
ctxt->timer = NULL;
}
ecore_main_loop_quit();
return ECORE_CALLBACK_CANCEL; // same as EINA_FALSE
}
return ECORE_CALLBACK_RENEW; // same as EINA_TRUE
}
static Eina_Bool
_timer_cb(void *data)
{
struct context *ctxt = data;
printf("TIMER: timer callback called.\n");
if (ctxt->timer)
ctxt->timer = NULL;
return ECORE_CALLBACK_CANCEL; // same as EINA_TRUE
}
int main(int argc, char **argv)
{
struct context ctxt = {0};
if (!ecore_init())
{
printf("ERROR: Cannot init Ecore!\n");
return -1;
}
_event_type = ecore_event_type_new();
ctxt.enterer = ecore_idle_enterer_add(_enterer_cb, &ctxt);
ctxt.exiter = ecore_idle_exiter_add(_exiter_cb, &ctxt);
ctxt.idler = ecore_idler_add(_idler_cb, &ctxt);
ctxt.handler = ecore_event_handler_add(_event_type,
_event_handler_cb,
&ctxt);
ctxt.timer = ecore_timer_add(0.0005, _timer_cb, &ctxt);
ecore_main_loop_begin();
ecore_shutdown();
return 0;
}

View File

@ -41,6 +41,9 @@ static int idle_enterers_delete_me = 0;
* @param data The data to be passed to the @p func call
* @return A handle to the idle enterer callback if successful. Otherwise,
* NULL is returned.
* @note The function func will be called every time the main loop is entering
* idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
* (or ECORE_CALLBACK_CANCEL) deletes the idle enterer.
*/
EAPI Ecore_Idle_Enterer *
ecore_idle_enterer_add(Ecore_Task_Cb func, const void *data)
@ -63,6 +66,9 @@ ecore_idle_enterer_add(Ecore_Task_Cb func, const void *data)
* @param data The data to be passed to the @p func call
* @return A handle to the idle enterer callback if successful. Otherwise,
* NULL is returned.
* @note The function func will be called every time the main loop is entering
* idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
* (or ECORE_CALLBACK_CANCEL) deletes the idle enterer.
*/
EAPI Ecore_Idle_Enterer *
ecore_idle_enterer_before_add(Ecore_Task_Cb func, const void *data)

View File

@ -40,6 +40,9 @@ static int idle_exiters_delete_me = 0;
* @param func The function to call when exiting an idle state.
* @param data The data to be passed to the @p func call
* @return A handle to the idle exiter callback on success. NULL otherwise.
* @note The function func will be called every time the main loop is exiting
* idle state, as long as it returns 1 (or ECORE_CALLBACK_RENEW). A return of 0
* (or ECORE_CALLBACK_CANCEL) deletes the idle exiter.
*/
EAPI Ecore_Idle_Exiter *
ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)

View File

@ -55,6 +55,13 @@ process.
Exiter callbacks are called when the main loop wakes up from an idle
state.
@note Idle state doesn't mean that the @b program is idle, but that the <b>main
loop</b> is idle. It doesn't have any timers, events, fd handlers or anything
else to process (which in most <em>event driven</em> programs also means that the @b
program is idle too, but it's not a rule). The program itself may be doing a lot of
processing in the idler, or in another thread, for example.
* @{
*/