ecore/idler - Improve documentation and add an example.
SVN revision: 60602
This commit is contained in:
parent
def2382a91
commit
d83f174929
|
@ -4,6 +4,7 @@
|
||||||
* Here is a page with some Ecore examples explained:
|
* Here is a page with some Ecore examples explained:
|
||||||
*
|
*
|
||||||
* @li @ref ecore_time_example_c
|
* @li @ref ecore_time_example_c
|
||||||
|
* @li @ref ecore_idler_example_c
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -37,6 +38,72 @@
|
||||||
* @include ecore_time_example.c
|
* @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
|
* @example ecore_time_example.c
|
||||||
* Shows the difference between the three time functions. See @ref
|
* Shows the difference between the three time functions. See @ref
|
||||||
|
|
|
@ -12,6 +12,7 @@ LDADD = \
|
||||||
@dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ @rt_libs@ -lm
|
@dlopen_libs@ @EINA_LIBS@ @EVIL_LIBS@ @GLIB_LIBS@ @WIN32_LIBS@ @LTLIBINTL@ @EFL_PTHREAD_LIBS@ @rt_libs@ -lm
|
||||||
|
|
||||||
SRCS = \
|
SRCS = \
|
||||||
|
ecore_idler_example.c \
|
||||||
ecore_time_example.c \
|
ecore_time_example.c \
|
||||||
client_bench.c \
|
client_bench.c \
|
||||||
server_bench.c \
|
server_bench.c \
|
||||||
|
@ -31,6 +32,7 @@ endif
|
||||||
|
|
||||||
if EFL_BUILD_EXAMPLES
|
if EFL_BUILD_EXAMPLES
|
||||||
pkglib_PROGRAMS += \
|
pkglib_PROGRAMS += \
|
||||||
|
ecore_idler_example \
|
||||||
ecore_time_example
|
ecore_time_example
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -41,6 +41,9 @@ static int idle_enterers_delete_me = 0;
|
||||||
* @param data The data to be passed to the @p func call
|
* @param data The data to be passed to the @p func call
|
||||||
* @return A handle to the idle enterer callback if successful. Otherwise,
|
* @return A handle to the idle enterer callback if successful. Otherwise,
|
||||||
* NULL is returned.
|
* 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 *
|
EAPI Ecore_Idle_Enterer *
|
||||||
ecore_idle_enterer_add(Ecore_Task_Cb func, const void *data)
|
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
|
* @param data The data to be passed to the @p func call
|
||||||
* @return A handle to the idle enterer callback if successful. Otherwise,
|
* @return A handle to the idle enterer callback if successful. Otherwise,
|
||||||
* NULL is returned.
|
* 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 *
|
EAPI Ecore_Idle_Enterer *
|
||||||
ecore_idle_enterer_before_add(Ecore_Task_Cb func, const void *data)
|
ecore_idle_enterer_before_add(Ecore_Task_Cb func, const void *data)
|
||||||
|
|
|
@ -40,6 +40,9 @@ static int idle_exiters_delete_me = 0;
|
||||||
* @param func The function to call when exiting an idle state.
|
* @param func The function to call when exiting an idle state.
|
||||||
* @param data The data to be passed to the @p func call
|
* @param data The data to be passed to the @p func call
|
||||||
* @return A handle to the idle exiter callback on success. NULL otherwise.
|
* @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 *
|
EAPI Ecore_Idle_Exiter *
|
||||||
ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)
|
ecore_idle_exiter_add(Ecore_Task_Cb func, const void *data)
|
||||||
|
|
|
@ -55,6 +55,13 @@ process.
|
||||||
|
|
||||||
Exiter callbacks are called when the main loop wakes up from an idle
|
Exiter callbacks are called when the main loop wakes up from an idle
|
||||||
state.
|
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.
|
||||||
|
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue