2004-10-20 10:51:29 -07:00
|
|
|
#ifdef WIN32
|
|
|
|
#include <winsock.h>
|
|
|
|
#endif
|
|
|
|
|
2006-01-01 12:29:34 -08:00
|
|
|
#include <math.h>
|
2003-09-23 01:09:32 -07:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
2006-01-06 22:48:56 -08:00
|
|
|
#define FIX_HZ 1
|
|
|
|
|
2004-06-09 03:35:01 -07:00
|
|
|
#ifdef FIX_HZ
|
|
|
|
#include <sys/param.h>
|
|
|
|
#ifndef HZ
|
|
|
|
#define HZ 100
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2006-01-06 22:48:56 -08:00
|
|
|
#include "ecore_private.h"
|
|
|
|
#include "Ecore.h"
|
2004-06-09 03:35:01 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
static int _ecore_main_select(double timeout);
|
|
|
|
static void _ecore_main_fd_handlers_cleanup(void);
|
|
|
|
static void _ecore_main_fd_handlers_call(void);
|
|
|
|
static int _ecore_main_fd_handlers_buf_call(void);
|
|
|
|
static void _ecore_main_loop_iterate_internal(int once_only);
|
|
|
|
|
2003-11-09 20:48:28 -08:00
|
|
|
static int in_main_loop = 0;
|
|
|
|
static int do_quit = 0;
|
|
|
|
static Ecore_Fd_Handler *fd_handlers = NULL;
|
|
|
|
static int fd_handlers_delete_me = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2004-03-16 21:14:13 -08:00
|
|
|
static double t1 = 0.0;
|
|
|
|
static double t2 = 0.0;
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/**
|
2004-09-22 01:17:15 -07:00
|
|
|
* @defgroup Ecore_Main_Loop_Group Main Loop Functions
|
|
|
|
*
|
|
|
|
* These functions control the Ecore event handling loop. This loop is
|
|
|
|
* designed to work on embedded systems all the way to large and
|
|
|
|
* powerful mutli-cpu workstations.
|
|
|
|
*
|
|
|
|
* It serialises all system signals and events into a single event
|
|
|
|
* queue, that can be easily processed without needing to worry about
|
|
|
|
* concurrency. A properly written, event-driven program using this
|
|
|
|
* kind of programming does not need threads. It makes the program very
|
|
|
|
* robust and easy to follow.
|
2003-09-23 01:09:32 -07:00
|
|
|
*
|
2004-09-22 01:17:15 -07:00
|
|
|
* Here is an example of simple program and its basic event loop flow:
|
|
|
|
* @image html prog_flow.png
|
|
|
|
*
|
|
|
|
* For examples of setting up and using a main loop, see
|
|
|
|
* @ref event_handler_example.c and @ref timer_example.c.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Runs a single iteration of the main loop to process everything on the
|
|
|
|
* queue.
|
|
|
|
* @ingroup Ecore_Main_Loop_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_loop_iterate(void)
|
|
|
|
{
|
|
|
|
_ecore_main_loop_iterate_internal(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-09-22 01:17:15 -07:00
|
|
|
* Runs the application main loop.
|
|
|
|
*
|
|
|
|
* This function will not return until @ref ecore_main_loop_quit is called.
|
|
|
|
*
|
2004-05-07 21:44:04 -07:00
|
|
|
* @ingroup Ecore_Main_Loop_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_loop_begin(void)
|
|
|
|
{
|
|
|
|
in_main_loop++;
|
|
|
|
for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0);
|
|
|
|
do_quit = 0;
|
|
|
|
in_main_loop--;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-09-22 01:17:15 -07:00
|
|
|
* Quits the main loop once all the events currently on the queue have
|
|
|
|
* been processed.
|
2004-05-07 21:44:04 -07:00
|
|
|
* @ingroup Ecore_Main_Loop_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_loop_quit(void)
|
|
|
|
{
|
|
|
|
do_quit = 1;
|
|
|
|
}
|
|
|
|
|
2004-09-22 01:17:15 -07:00
|
|
|
/**
|
|
|
|
* @defgroup Ecore_FD_Handler_Group File Event Handling Functions
|
|
|
|
*
|
2004-09-22 21:05:13 -07:00
|
|
|
* Functions that deal with file descriptor handlers.
|
2004-09-22 01:17:15 -07:00
|
|
|
*/
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/**
|
2004-09-22 21:05:13 -07:00
|
|
|
* Adds a callback for activity on the given file descriptor.
|
|
|
|
*
|
|
|
|
* @p func will be called during the execution of @ref ecore_main_loop_begin
|
|
|
|
* when the file descriptor is available for reading, or writing, or both.
|
2005-12-18 17:36:55 -08:00
|
|
|
*
|
|
|
|
* Normally the return value from the @p func is "zero means this handler is
|
|
|
|
* finished and can be deleted" as is usual for handler callbacks. However,
|
|
|
|
* if the @p buf_func is supplied, then the return value from the @p func is "non
|
|
|
|
* zero means the handler should be called again in a tight loop".
|
|
|
|
*
|
2004-09-22 21:05:13 -07:00
|
|
|
* @p buf_func is called during event loop handling to check if data that has
|
|
|
|
* been read from the file descriptor is in a buffer and is available to
|
2005-12-18 17:36:55 -08:00
|
|
|
* read. Some systems (notably xlib) handle their own buffering, and would
|
|
|
|
* otherwise not work with select(). These systems should use a @p buf_func.
|
|
|
|
* This is a most annoying hack, only ecore_x uses it, so refer to that for
|
|
|
|
* an example. NOTE - @p func should probably return "one" always if @p buf_func
|
|
|
|
* is used, to avoid confusion with the other return walue semantics.
|
2004-09-22 21:05:13 -07:00
|
|
|
*
|
|
|
|
* @param fd The file descriptor to watch.
|
|
|
|
* @param flags To watch it for read (@c ECORE_FD_READ) and/or
|
|
|
|
* (@c ECORE_FD_WRITE) write ability. @c ECORE_FD_ERROR
|
2006-01-10 08:46:07 -08:00
|
|
|
*
|
2004-09-22 21:05:13 -07:00
|
|
|
* @param func The callback function.
|
|
|
|
* @param data The data to pass to the callback.
|
|
|
|
* @param buf_func The function to call to check if any data has been
|
|
|
|
* buffered and already read from the fd. Can be @c NULL.
|
|
|
|
* @param buf_data The data to pass to the @p buf_func function.
|
|
|
|
* @return A fd handler handle if successful. @c NULL otherwise.
|
|
|
|
* @ingroup Ecore_FD_Handler_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI Ecore_Fd_Handler *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data)
|
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
if ((fd < 0) ||
|
|
|
|
(flags == 0) ||
|
|
|
|
(!func)) return NULL;
|
|
|
|
fdh = calloc(1, sizeof(Ecore_Fd_Handler));
|
|
|
|
if (!fdh) return NULL;
|
|
|
|
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
|
|
|
|
fdh->fd = fd;
|
|
|
|
fdh->flags = flags;
|
|
|
|
fdh->read_active = 0;
|
|
|
|
fdh->write_active = 0;
|
2004-02-24 11:45:01 -08:00
|
|
|
fdh->error_active = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
fdh->delete_me = 0;
|
|
|
|
fdh->func = func;
|
|
|
|
fdh->data = (void *)data;
|
|
|
|
fdh->buf_func = buf_func;
|
|
|
|
fdh->buf_data = (void *)buf_data;
|
2005-08-30 03:05:27 -07:00
|
|
|
fd_handlers = _ecore_list2_append(fd_handlers, fdh);
|
2003-09-23 01:09:32 -07:00
|
|
|
return fdh;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-09-22 21:05:13 -07:00
|
|
|
* Deletes the given FD handler.
|
|
|
|
* @param fd_handler The given FD handler.
|
|
|
|
* @return The data pointer set using @ref ecore_main_fd_handler_add,
|
|
|
|
* for @p fd_handler on success. @c NULL otherwise.
|
|
|
|
* @ingroup Ecore_FD_Handler_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void *
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
|
|
|
|
{
|
|
|
|
if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
|
|
|
|
"ecore_main_fd_handler_del");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
fd_handler->delete_me = 1;
|
|
|
|
fd_handlers_delete_me = 1;
|
|
|
|
return fd_handler->data;
|
|
|
|
}
|
|
|
|
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2005-03-28 00:55:59 -08:00
|
|
|
ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data)
|
|
|
|
{
|
|
|
|
if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
|
|
|
|
"ecore_main_fd_handler_prepare_callback_set");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fd_handler->prep_func = func;
|
2005-03-28 01:00:08 -08:00
|
|
|
fd_handler->prep_data = (void *) data;
|
2005-03-28 00:55:59 -08:00
|
|
|
}
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/**
|
2004-09-22 21:05:13 -07:00
|
|
|
* Retrieves the file descriptor that the given handler is handling.
|
2004-09-22 01:17:15 -07:00
|
|
|
* @param fd_handler The given FD handler.
|
2004-09-22 21:05:13 -07:00
|
|
|
* @return The file descriptor the handler is watching.
|
2004-09-22 01:17:15 -07:00
|
|
|
* @ingroup Ecore_FD_Handler_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
|
|
|
|
{
|
|
|
|
if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
|
|
|
|
"ecore_main_fd_handler_fd_get");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return fd_handler->fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-09-22 21:05:13 -07:00
|
|
|
* Return if read, write or error, or a combination thereof, is active on the
|
|
|
|
* file descriptor of the given FD handler.
|
|
|
|
* @param fd_handler The given FD handler.
|
|
|
|
* @param flags The flags, @c ECORE_FD_READ, @c ECORE_FD_WRITE or
|
|
|
|
* @c ECORE_FD_ERROR to query.
|
|
|
|
* @return @c 1 if any of the given flags are active. @c 0 otherwise.
|
|
|
|
* @ingroup Ecore_FD_Handler_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
|
|
|
|
"ecore_main_fd_handler_active_get");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = 1;
|
|
|
|
if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = 1;
|
2004-02-24 11:45:01 -08:00
|
|
|
if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = 1;
|
2003-09-23 01:09:32 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2004-09-22 21:05:13 -07:00
|
|
|
* Set what active streams the given FD handler should be monitoring.
|
|
|
|
* @param fd_handler The given FD handler.
|
|
|
|
* @param flags The flags to be watching.
|
|
|
|
* @ingroup Ecore_FD_Handler_Group
|
2003-09-23 01:09:32 -07:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI void
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags)
|
|
|
|
{
|
|
|
|
if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
|
|
|
|
{
|
|
|
|
ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
|
|
|
|
"ecore_main_fd_handler_active_set");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fd_handler->flags = flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_main_shutdown(void)
|
|
|
|
{
|
|
|
|
if (in_main_loop)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"\n"
|
|
|
|
"*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n"
|
|
|
|
"*** Program may crash or behave strangely now.\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
while (fd_handlers)
|
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = fd_handlers;
|
2005-08-30 03:05:27 -07:00
|
|
|
fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
|
2003-09-23 01:09:32 -07:00
|
|
|
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
|
|
|
|
free(fdh);
|
|
|
|
}
|
|
|
|
fd_handlers_delete_me = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_ecore_main_select(double timeout)
|
|
|
|
{
|
|
|
|
struct timeval tv, *t;
|
2004-02-24 11:45:01 -08:00
|
|
|
fd_set rfds, wfds, exfds;
|
2003-09-23 01:09:32 -07:00
|
|
|
int max_fd;
|
|
|
|
int ret;
|
2005-08-30 03:05:27 -07:00
|
|
|
Ecore_List2 *l;
|
2004-06-09 03:35:01 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
t = NULL;
|
2006-01-01 12:29:34 -08:00
|
|
|
if ((!finite(timeout)) || (timeout == 0.0)) /* finite() tests for NaN, too big, too small, and infinity. */
|
|
|
|
{
|
|
|
|
tv.tv_sec = 0;
|
|
|
|
tv.tv_usec = 0;
|
|
|
|
t = &tv;
|
|
|
|
}
|
|
|
|
else if (timeout > 0.0)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
int sec, usec;
|
2004-06-09 03:35:01 -07:00
|
|
|
|
|
|
|
#ifdef FIX_HZ
|
|
|
|
timeout += (0.5 / HZ);
|
2003-09-23 01:09:32 -07:00
|
|
|
sec = (int)timeout;
|
|
|
|
usec = (int)((timeout - (double)sec) * 1000000);
|
2004-06-09 03:35:01 -07:00
|
|
|
#else
|
|
|
|
sec = (int)timeout;
|
|
|
|
usec = (int)((timeout - (double)sec) * 1000000);
|
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
tv.tv_sec = sec;
|
|
|
|
tv.tv_usec = usec;
|
|
|
|
t = &tv;
|
|
|
|
}
|
|
|
|
max_fd = 0;
|
|
|
|
FD_ZERO(&rfds);
|
|
|
|
FD_ZERO(&wfds);
|
2004-02-24 11:45:01 -08:00
|
|
|
FD_ZERO(&exfds);
|
2005-03-28 00:55:59 -08:00
|
|
|
|
|
|
|
/* call the prepare callback for all handlers */
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
|
2005-03-28 00:55:59 -08:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
|
2005-09-20 12:15:49 -07:00
|
|
|
if (!fdh->delete_me && fdh->prep_func)
|
2005-03-28 00:55:59 -08:00
|
|
|
fdh->prep_func (fdh->prep_data, fdh);
|
|
|
|
}
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
if (fdh->flags & ECORE_FD_READ)
|
|
|
|
{
|
|
|
|
FD_SET(fdh->fd, &rfds);
|
|
|
|
if (fdh->fd > max_fd) max_fd = fdh->fd;
|
|
|
|
}
|
|
|
|
if (fdh->flags & ECORE_FD_WRITE)
|
|
|
|
{
|
|
|
|
FD_SET(fdh->fd, &wfds);
|
|
|
|
if (fdh->fd > max_fd) max_fd = fdh->fd;
|
|
|
|
}
|
2004-02-24 18:24:59 -08:00
|
|
|
if (fdh->flags & ECORE_FD_ERROR)
|
2004-02-24 11:45:01 -08:00
|
|
|
{
|
2004-02-24 18:24:59 -08:00
|
|
|
FD_SET(fdh->fd, &exfds);
|
|
|
|
if (fdh->fd > max_fd) max_fd = fdh->fd;
|
2004-02-24 11:45:01 -08:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
if (_ecore_signal_count_get()) return -1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2004-02-24 11:45:01 -08:00
|
|
|
ret = select(max_fd + 1, &rfds, &wfds, &exfds, t);
|
2003-09-23 01:09:32 -07:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
if (errno == EINTR) return -1;
|
|
|
|
}
|
|
|
|
if (ret > 0)
|
|
|
|
{
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
if (!fdh->delete_me)
|
|
|
|
{
|
|
|
|
if (FD_ISSET(fdh->fd, &rfds))
|
|
|
|
fdh->read_active = 1;
|
|
|
|
if (FD_ISSET(fdh->fd, &wfds))
|
|
|
|
fdh->write_active = 1;
|
2004-02-24 11:45:01 -08:00
|
|
|
if (FD_ISSET(fdh->fd, &exfds))
|
|
|
|
fdh->error_active = 1;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ecore_main_fd_handlers_cleanup();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_main_fd_handlers_cleanup(void)
|
|
|
|
{
|
2005-08-30 03:05:27 -07:00
|
|
|
Ecore_List2 *l;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
if (!fd_handlers_delete_me) return;
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l;)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
l = l->next;
|
|
|
|
if (fdh->delete_me)
|
|
|
|
{
|
2005-08-30 03:05:27 -07:00
|
|
|
fd_handlers = _ecore_list2_remove(fd_handlers, fdh);
|
2003-09-23 01:09:32 -07:00
|
|
|
ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
|
|
|
|
free(fdh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fd_handlers_delete_me = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_main_fd_handlers_call(void)
|
|
|
|
{
|
2005-08-30 03:05:27 -07:00
|
|
|
Ecore_List2 *l;
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
if (!fdh->delete_me)
|
|
|
|
{
|
2004-02-24 18:24:59 -08:00
|
|
|
if ((fdh->read_active) ||
|
|
|
|
(fdh->write_active) ||
|
|
|
|
(fdh->error_active))
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
if (!fdh->func(fdh->data, fdh))
|
|
|
|
{
|
|
|
|
fdh->delete_me = 1;
|
|
|
|
fd_handlers_delete_me = 1;
|
|
|
|
}
|
|
|
|
fdh->read_active = 0;
|
|
|
|
fdh->write_active = 0;
|
2004-02-24 11:45:01 -08:00
|
|
|
fdh->error_active = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
_ecore_main_fd_handlers_buf_call(void)
|
|
|
|
{
|
2005-08-30 03:05:27 -07:00
|
|
|
Ecore_List2 *l;
|
2003-09-23 01:09:32 -07:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = 0;
|
2005-08-30 03:05:27 -07:00
|
|
|
for (l = (Ecore_List2 *)fd_handlers; l; l = l->next)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
Ecore_Fd_Handler *fdh;
|
|
|
|
|
|
|
|
fdh = (Ecore_Fd_Handler *)l;
|
|
|
|
if (!fdh->delete_me)
|
|
|
|
{
|
|
|
|
if (fdh->buf_func)
|
|
|
|
{
|
|
|
|
if (fdh->buf_func(fdh->buf_data, fdh))
|
|
|
|
{
|
|
|
|
ret |= fdh->func(fdh->data, fdh);
|
|
|
|
fdh->read_active = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_main_loop_iterate_internal(int once_only)
|
|
|
|
{
|
|
|
|
double next_time;
|
2005-03-01 23:06:44 -08:00
|
|
|
int have_event = 0;
|
2003-09-23 01:09:32 -07:00
|
|
|
int have_signal;
|
|
|
|
|
|
|
|
in_main_loop++;
|
|
|
|
/* expire any timers */
|
|
|
|
{
|
|
|
|
double now;
|
|
|
|
|
|
|
|
now = ecore_time_get();
|
|
|
|
while (_ecore_timer_call(now));
|
|
|
|
_ecore_timer_cleanup();
|
|
|
|
}
|
|
|
|
/* any timers re-added as a result of these are allowed to go */
|
|
|
|
_ecore_timer_enable_new();
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
/* process signals into events .... */
|
|
|
|
while (_ecore_signal_count_get()) _ecore_signal_call();
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
if (_ecore_event_exist())
|
|
|
|
{
|
2004-06-09 03:35:01 -07:00
|
|
|
int ret;
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
have_event = 1;
|
|
|
|
have_signal = 1;
|
2004-06-09 03:35:01 -07:00
|
|
|
ret = _ecore_main_select(0);
|
2003-09-23 01:09:32 -07:00
|
|
|
goto process_events;
|
|
|
|
}
|
|
|
|
/* call idle enterers ... */
|
|
|
|
if (!once_only)
|
|
|
|
_ecore_idle_enterer_call();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
have_event = have_signal = 0;
|
|
|
|
ret = _ecore_main_select(0);
|
|
|
|
|
|
|
|
if (ret > 0) have_event = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
if (_ecore_signal_count_get() > 0) have_signal = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
if (have_signal || have_event)
|
|
|
|
goto process_events;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if these calls caused any biuffered events to appear - deal with them */
|
|
|
|
while (_ecore_main_fd_handlers_buf_call());
|
|
|
|
/* if ther are any - jump to processing them */
|
|
|
|
if (_ecore_event_exist())
|
|
|
|
{
|
2004-06-09 03:35:01 -07:00
|
|
|
int ret;
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
have_event = 1;
|
|
|
|
have_signal = 1;
|
2004-06-09 03:35:01 -07:00
|
|
|
ret = _ecore_main_select(0);
|
2003-09-23 01:09:32 -07:00
|
|
|
goto process_events;
|
|
|
|
}
|
|
|
|
if (once_only)
|
|
|
|
{
|
|
|
|
_ecore_idle_enterer_call();
|
|
|
|
in_main_loop--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2004-03-16 21:14:13 -08:00
|
|
|
if (_ecore_fps_debug)
|
|
|
|
{
|
|
|
|
t2 = ecore_time_get();
|
|
|
|
if ((t1 > 0.0) && (t2 > 0.0))
|
|
|
|
_ecore_fps_debug_runtime_add(t2 - t1);
|
|
|
|
}
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
start_loop:
|
2004-05-12 20:20:13 -07:00
|
|
|
if (do_quit)
|
|
|
|
{
|
|
|
|
in_main_loop--;
|
|
|
|
return;
|
|
|
|
}
|
2004-11-07 16:08:26 -08:00
|
|
|
if (!_ecore_event_exist())
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2004-11-07 16:08:26 -08:00
|
|
|
/* init flags */
|
|
|
|
have_event = have_signal = 0;
|
|
|
|
next_time = _ecore_timer_next_get();
|
|
|
|
/* no timers */
|
|
|
|
if (next_time < 0)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2004-11-07 16:08:26 -08:00
|
|
|
/* no idlers */
|
|
|
|
if (!_ecore_idler_exist())
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2004-11-07 16:08:26 -08:00
|
|
|
ret = _ecore_main_select(-1);
|
2003-09-23 01:09:32 -07:00
|
|
|
if (ret > 0) have_event = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
if (_ecore_signal_count_get() > 0) have_signal = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-11-07 16:08:26 -08:00
|
|
|
/* idlers */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!_ecore_idler_call()) goto start_loop;
|
|
|
|
if (_ecore_event_exist()) break;
|
|
|
|
ret = _ecore_main_select(0);
|
|
|
|
if (ret > 0) have_event = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2004-11-07 16:08:26 -08:00
|
|
|
if (_ecore_signal_count_get() > 0) have_signal = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2004-11-07 16:08:26 -08:00
|
|
|
if (have_event || have_signal) break;
|
|
|
|
next_time = _ecore_timer_next_get();
|
|
|
|
if (next_time >= 0) goto start_loop;
|
|
|
|
if (do_quit) break;
|
|
|
|
}
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-11-07 16:08:26 -08:00
|
|
|
/* timers */
|
2003-09-23 01:09:32 -07:00
|
|
|
else
|
|
|
|
{
|
2004-11-07 16:08:26 -08:00
|
|
|
/* no idlers */
|
|
|
|
if (!_ecore_idler_exist())
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2004-11-07 16:08:26 -08:00
|
|
|
ret = _ecore_main_select(next_time);
|
2003-09-23 01:09:32 -07:00
|
|
|
if (ret > 0) have_event = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
if (_ecore_signal_count_get() > 0) have_signal = 1;
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2004-11-07 16:08:26 -08:00
|
|
|
}
|
|
|
|
/* idlers */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
double cur_time, t;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!_ecore_idler_call()) goto start_loop;
|
|
|
|
if (_ecore_event_exist()) break;
|
|
|
|
ret = _ecore_main_select(0);
|
|
|
|
if (ret > 0) have_event = 1;
|
|
|
|
#ifndef WIN32
|
|
|
|
if (_ecore_signal_count_get() > 0) have_signal = 1;
|
|
|
|
#endif
|
|
|
|
if ((have_event) || (have_signal)) break;
|
|
|
|
cur_time = ecore_time_get();
|
|
|
|
t = ecore_time_get() - cur_time;
|
|
|
|
if (t >= next_time) break;
|
|
|
|
next_time = _ecore_timer_next_get();
|
|
|
|
if (next_time < 0) goto start_loop;
|
|
|
|
if (do_quit) break;
|
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2004-03-16 21:14:13 -08:00
|
|
|
if (_ecore_fps_debug)
|
|
|
|
{
|
|
|
|
t1 = ecore_time_get();
|
|
|
|
}
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2004-03-16 21:14:13 -08:00
|
|
|
/* we came out of our "wait state" so idle has exited */
|
|
|
|
if (!once_only)
|
|
|
|
_ecore_idle_exiter_call();
|
2003-09-23 01:09:32 -07:00
|
|
|
/* call the fd handler per fd that became alive... */
|
|
|
|
/* this should read or write any data to the monitored fd and then */
|
|
|
|
/* post events onto the ecore event pipe if necessary */
|
|
|
|
process_events:
|
|
|
|
if (have_event) _ecore_main_fd_handlers_call();
|
|
|
|
do
|
|
|
|
{
|
2004-10-20 10:51:29 -07:00
|
|
|
#ifndef WIN32
|
2003-09-23 01:09:32 -07:00
|
|
|
/* process signals into events .... */
|
|
|
|
while (_ecore_signal_count_get()) _ecore_signal_call();
|
2004-10-20 10:51:29 -07:00
|
|
|
#endif
|
2003-09-23 01:09:32 -07:00
|
|
|
|
|
|
|
/* handle events ... */
|
|
|
|
_ecore_event_call();
|
|
|
|
_ecore_main_fd_handlers_cleanup();
|
|
|
|
}
|
|
|
|
while (_ecore_main_fd_handlers_buf_call());
|
|
|
|
if (once_only) _ecore_idle_enterer_call();
|
|
|
|
in_main_loop--;
|
|
|
|
}
|