From: Enlightenment C. <no...@cv...> - 2008-01-11 07:34:32
|
Enlightenment CVS committal Author : raster Project : e17 Module : libs/ecore Dir : e17/libs/ecore/src/lib/ecore Modified Files: Ecore.h Makefile.am ecore.c ecore_exe.c ecore_idle_enterer.c ecore_private.h ecore_timer.c Added Files: ecore_poll.c Log Message: e: 1. configure/build changes to allow cross-compiling painlessly 2. pager module namespace changes - this was still dirty afdter the namespace cleanup, so clean it up 3. add a powersave subsystem - doesnt have an "automatic" way to turn on and off right now, this i think is best provided by modules (that do things like monitor acpi status's (eg close lid of laptop), AC power status etc. etc. this allows e to nicely defer "power" expensive actions to avoid disk spinups etc. 4. move to use the new ecore poller system - discussed long ago as part of power management/saving issues. now it exists 5. add a canvas idle flush call that helsp cope with the new shm greedy software x11 engine stuff 6. use the new powersave subsystem where appropriate 7. fix non-zeroed/initted memory access in e_fm_main 8. fix mem leak for e menus 9. remove ipc handlers for changed/removed config values 10. use animaotr not timer for menu scrolls - then menu scrolls obey the fps config 11. fix up timer/poll happienss of cursor idle stuff 12. remove avoid damage from popups for now - causing problems 13. change battery and temp readouts to b e shorter so they fit 14. pager can emit signals on focus change for mini-windows now 15. temperature module now uses a slave process and uses stdin/out to talk to it and get output - this makes e smoother as in my expereicne i found getting the temp on my laptop actually took like 200ms so e "hang" for 200ms while reading the acpi files - so now the subprocess does it and just writesa back to e when it gets it. ecore: 1. add ecore_pollers. see the documentation on them in doxygen comments :) 2. fix timers to only go off when they have to - bug there that made e's select time out a LOT more than it needed to. defensive coding hid the problem. now fixed. e should be much more power friendly now. 3. formatting/niceness in ecore_exe stuff 4. some comments on comments with SIGIO ideas vs. select 5. add call to be able to add an idle enterer at the start of the list of them, not just the end (as has been the default) 6. fix ecore_evas to support auto evas idler calls after 0.5 secs of idle in all canvases - and to do it right 7. if argb destination - set the shape EVENT shape (to mask out events in transparent regions much like shape does withotu translucency) 8. in ecore_x add support for the event shape evas: 1. fix cache to work properly and not just always fill up (as it seemed to like to think cahce useage dropped below 0 when it didnt and thus just over-fill) 2. software x11 engine now ONLY uses shm segments - no ximages over the socket. this ximage hack was there to avoid the 2 round trips involved in setting up an shm image - now i mitigated that wih an shm image cache pool. it keeps shm images around and repurposes them for new update regions if appropriate. this means many fewer shm creates (about 1/100th the number) and since we recycle the memory less 0 memory page filling by the kernel - in the end, i recorded about a 10-20% speedup over the old software x11 engine. simple tests i have seen up to 120% speedups. idle flush now does something - it frees all the cached shm segments. it has a hard-coded limit of 4mb worth of shm segments (or 32 segments - whichever comes first) to keep around. once can never complain much about speedups methinks :). also evas will defer sync until the NEXT frame is written - this means evas can calculate the next frame of data while x dma's/copies the images to the screen at the same time (if you hve a dual core or multi-cpu machnike or your xserver is able to use DMA to copy image data to the screen/video ram then this should see a decent speedup). =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/Ecore.h,v retrieving revision 1.56 retrieving revision 1.57 diff -u -3 -r1.56 -r1.57 --- Ecore.h 25 Oct 2007 05:55:07 -0000 1.56 +++ Ecore.h 11 Jan 2008 07:33:56 -0000 1.57 @@ -85,18 +85,23 @@ enum _Ecore_Exe_Flags /* flags for executing a child with its stdin and/or stdout piped back */ { - - ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */ - ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */ - ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */ - ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */ - ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */ - ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */ - ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */ - ECORE_EXE_USE_SH = 128 /**< Use /bin/sh to run the command. */ + ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */ + ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */ + ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */ + ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */ + ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */ + ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */ + ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */ + ECORE_EXE_USE_SH = 128 /**< Use /bin/sh to run the command. */ }; typedef enum _Ecore_Exe_Flags Ecore_Exe_Flags; + enum _Ecore_Poller_Type /* Poller types */ + { + ECORE_POLLER_CORE = 0 /**< The core poller interval */ + }; + typedef enum _Ecore_Poller_Type Ecore_Poller_Type; + #ifndef _WIN32 typedef void Ecore_Exe; /**< A handle for spawned processes */ #endif @@ -109,6 +114,7 @@ typedef void Ecore_Event_Filter; /**< A handle for an event filter */ typedef void Ecore_Event; /**< A handle for an event */ typedef void Ecore_Animator; /**< A handle for animators */ + typedef void Ecore_Poller; /**< A handle for pollers */ #endif typedef struct _Ecore_Event_Signal_User Ecore_Event_Signal_User; /**< User signal event */ typedef struct _Ecore_Event_Signal_Hup Ecore_Event_Signal_Hup; /**< Hup signal event */ @@ -250,6 +256,7 @@ EAPI void *ecore_idler_del(Ecore_Idler *idler); EAPI Ecore_Idle_Enterer *ecore_idle_enterer_add(int (*func) (void *data), const void *data); + EAPI Ecore_Idle_Enterer *ecore_idle_enterer_before_add(int (*func) (void *data), const void *data); EAPI void *ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer); EAPI Ecore_Idle_Exiter *ecore_idle_exiter_add(int (*func) (void *data), const void *data); @@ -276,6 +283,12 @@ EAPI void ecore_animator_frametime_set(double frametime); EAPI double ecore_animator_frametime_get(void); + EAPI void ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time); + EAPI double ecore_poller_poll_interval_get(Ecore_Poller_Type type); + EAPI Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data); + EAPI void *ecore_poller_del(Ecore_Poller *poller); + + #ifdef __cplusplus } #endif =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/Makefile.am,v retrieving revision 1.13 retrieving revision 1.14 diff -u -3 -r1.13 -r1.14 --- Makefile.am 4 Nov 2007 09:29:18 -0000 1.13 +++ Makefile.am 11 Jan 2008 07:33:56 -0000 1.14 @@ -31,6 +31,7 @@ ecore_timer.c \ ecore_tree.c \ ecore_value.c \ +ecore_poll.c \ ecore_private.h libecore_la_LIBADD = @dlopen_libs@ @winsock_libs@ -lm =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/ecore.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -3 -r1.20 -r1.21 --- ecore.c 27 Oct 2007 10:58:00 -0000 1.20 +++ ecore.c 11 Jan 2008 07:33:56 -0000 1.21 @@ -84,6 +84,7 @@ return _ecore_init_count; if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); + _ecore_poller_shutdown(); _ecore_animator_shutdown(); #ifndef _WIN32 _ecore_exe_shutdown(); =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/ecore_exe.c,v retrieving revision 1.69 retrieving revision 1.70 diff -u -3 -r1.69 -r1.70 --- ecore_exe.c 26 Aug 2007 11:17:20 -0000 1.69 +++ ecore_exe.c 11 Jan 2008 07:33:56 -0000 1.70 @@ -260,7 +260,7 @@ * terminated event have been called, the handle will be freed by Ecore. * * This function does the same thing as ecore_exe_run(), but also makes the - * standard in and/or out as wel las stderr from the child process available + * standard in and/or out as well as stderr from the child process available * for reading or writing. To write use ecore_exe_send(). To read listen to * ECORE_EXE_EVENT_DATA or ECORE_EXE_EVENT_ERROR events (set up handlers). * Ecore may buffer read and error data until a newline character if asked @@ -288,16 +288,14 @@ int ok = 1; int result; - if (!exe_cmd) - return NULL; - + if (!exe_cmd) return NULL; exe = calloc(1, sizeof(Ecore_Exe)); - if (exe == NULL) - return NULL; + if (exe == NULL) return NULL; if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR)) && (!(flags & ECORE_EXE_PIPE_READ))) - flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR; /* We need something to auto pipe. */ + /* We need something to auto pipe. */ + flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR; exe->child_fd_error = -1; exe->child_fd_read = -1; @@ -308,37 +306,44 @@ /* Create some pipes. */ if (ok) - E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) { + E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok) + { + } } if (ok && (flags & ECORE_EXE_PIPE_ERROR)) - E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) { - exe->child_fd_error = errorPipe[0]; - exe->child_fd_error_x = errorPipe[1]; + E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok) + { + exe->child_fd_error = errorPipe[0]; + exe->child_fd_error_x = errorPipe[1]; + } } if (ok && (flags & ECORE_EXE_PIPE_READ)) - E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) { - exe->child_fd_read = readPipe[0]; - exe->child_fd_read_x = readPipe[1]; + E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok) + { + exe->child_fd_read = readPipe[0]; + exe->child_fd_read_x = readPipe[1]; + } } if (ok && (flags & ECORE_EXE_PIPE_WRITE)) - E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) { - exe->child_fd_write = writePipe[1]; - exe->child_fd_write_x = writePipe[0]; + E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok) + { + exe->child_fd_write = writePipe[1]; + exe->child_fd_write_x = writePipe[0]; + } } - if (ok) { pid_t pid = 0; volatile int vfork_exec_errno = 0; - + /* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */ /* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */ pid = fork(); - + if (pid == -1) { fprintf(stderr, "Failed to fork process\n"); @@ -346,8 +351,9 @@ } else if (pid == 0) /* child */ { - /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the second pipe if it's open. */ - /* On the other hand, there was the Great FD Leak Scare of '06, so let's be paranoid. */ + /* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the + * second pipe if it's open. On the other hand, there was the + * Great FD Leak Scare of '06, so let's be paranoid. */ if (ok && (flags & ECORE_EXE_PIPE_ERROR)) { E_NO_ERRNO(result, close(STDERR_FILENO), ok); @@ -369,10 +375,10 @@ /* Setup the status pipe. */ E_NO_ERRNO(result, close(statusPipe[0]), ok); E_IF_NO_ERRNO(result, fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC), ok) /* close on exec shows sucess */ - { - /* Run the actual command. */ - _ecore_exe_exec_it(exe_cmd, flags); /* Should not return from this. */ - } + { + /* Run the actual command. */ + _ecore_exe_exec_it(exe_cmd, flags); /* no return */ + } } /* Something went 'orribly wrong. */ @@ -380,13 +386,13 @@ /* Close the pipes. */ if (flags & ECORE_EXE_PIPE_ERROR) - E_NO_ERRNO(result, close(errorPipe[1]), ok); + E_NO_ERRNO(result, close(errorPipe[1]), ok); if (flags & ECORE_EXE_PIPE_READ) - E_NO_ERRNO(result, close(readPipe[1]), ok); + E_NO_ERRNO(result, close(readPipe[1]), ok); if (flags & ECORE_EXE_PIPE_WRITE) - E_NO_ERRNO(result, close(writePipe[0]), ok); + E_NO_ERRNO(result, close(writePipe[0]), ok); E_NO_ERRNO(result, close(statusPipe[1]), ok); - + _exit(-1); } else /* parent */ @@ -394,13 +400,28 @@ /* Close the unused pipes. */ E_NO_ERRNO(result, close(statusPipe[1]), ok); - /* FIXME: after having a good look at the current e fd handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */ + /* FIXME: after having a good look at the current e fd + * handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */ + /* FIXME: above F_SETSIG etc. - this is async SIGIO based IO + * which is also linux specific so we probably don't want to + * do this as long as select() is working fine. the only time + * we really want to think of SIGIO async IO is when it all + * actually works basically everywhere and we can turn all + * IO into DMA async activities (i.e. you do a read() then + * the read is complete not on return but when you get a + * SIGIO - the read() just starts the transfer and it is + * completed in the background by DMA (or whatever mechanism + * the kernel choses)) */ /* Wait for it to start executing. */ - while (1) + /* FIXME: this doesn't seem very nice - we sit and block + * waiting on a child process... even though it's just + * the segment between the fork() and the exec) it just feels + * wrong */ + for (;;) { char buf; - + E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok); if (result == 0) { @@ -433,7 +454,7 @@ if ((exe->cmd = strdup(exe_cmd))) { if (flags & ECORE_EXE_PIPE_ERROR) - { /* Setup the error stuff. */ + { /* Setup the error stuff. */ E_IF_NO_ERRNO(result, fcntl(exe->child_fd_error, F_SETFL, O_NONBLOCK), ok) {} @@ -454,7 +475,7 @@ } } if (ok && (flags & ECORE_EXE_PIPE_READ)) - { /* Setup the read stuff. */ + { /* Setup the read stuff. */ E_IF_NO_ERRNO(result, fcntl(exe->child_fd_read, F_SETFL, O_NONBLOCK), ok) {} @@ -497,35 +518,34 @@ ok = 0; } } - + exes = _ecore_list2_append(exes, exe); n = 0; } else - ok = 0; + ok = 0; } else - ok = 0; + ok = 0; } if (!ok) - { /* Something went wrong, so pull down everything. */ - if (exe->pid) - ecore_exe_terminate(exe); + { /* Something went wrong, so pull down everything. */ + if (exe->pid) ecore_exe_terminate(exe); IF_FN_DEL(ecore_exe_free, exe); } else { Ecore_Exe_Event_Add *e; - + e = _ecore_exe_event_add_new(); e->exe = exe; - if (e) /* Send the event. */ - ecore_event_add(ECORE_EXE_EVENT_ADD, e, - _ecore_exe_event_add_free, NULL); + if (e) /* Send the event. */ + ecore_event_add(ECORE_EXE_EVENT_ADD, e, + _ecore_exe_event_add_free, NULL); /* printf("Running as %d for %s.\n", exe->pid, exe->cmd); */ } - + errno = n; return exe; } @@ -549,8 +569,7 @@ void *buf; buf = realloc(exe->write_data_buf, exe->write_data_size + size); - if (buf == NULL) - return 0; + if (buf == NULL) return 0; exe->write_data_buf = buf; memcpy((char *)exe->write_data_buf + exe->write_data_size, data, size); @@ -1365,7 +1384,10 @@ lost_exe = 0; errno = 0; - if ((num = read(child_fd, buf, READBUFSIZ)) < 1) /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE (currently 64k) to inbuf, use that instead of buf, and save ourselves a memcpy(). */ + if ((num = read(child_fd, buf, READBUFSIZ)) < 1) + /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE + * (currently 64k) to inbuf, use that instead of buf, and + * save ourselves a memcpy(). */ { lost_exe = ((errno == EIO) || (errno == EBADF) || =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/ecore_idle_enterer.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -3 -r1.7 -r1.8 --- ecore_idle_enterer.c 6 Jan 2006 17:58:12 -0000 1.7 +++ ecore_idle_enterer.c 11 Jan 2008 07:33:56 -0000 1.8 @@ -28,6 +28,29 @@ } /** + * Add an idle enterer handler at the start of the list so it gets called earlier than others. + * @param func The function to call when entering an idle state. + * @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. + * @ingroup Idle_Group + */ +EAPI Ecore_Idle_Enterer * +ecore_idle_enterer_before_add(int (*func) (void *data), const void *data) +{ + Ecore_Idle_Enterer *ie; + + if (!func) return NULL; + ie = calloc(1, sizeof(Ecore_Idle_Enterer)); + if (!ie) return NULL; + ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER); + ie->func = func; + ie->data = (void *)data; + idle_enterers = _ecore_list2_prepend(idle_enterers, ie); + return ie; +} + +/** * Delete an idle enterer callback. * @param idle_enterer The idle enterer to delete * @return The data pointer passed to the idler enterer callback on success. =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/ecore_private.h,v retrieving revision 1.45 retrieving revision 1.46 diff -u -3 -r1.45 -r1.46 --- ecore_private.h 27 Oct 2007 16:22:10 -0000 1.45 +++ ecore_private.h 11 Jan 2008 07:33:56 -0000 1.46 @@ -88,6 +88,7 @@ #define ECORE_MAGIC_EVENT_FILTER 0xf78218ff #define ECORE_MAGIC_EVENT 0xf77119fe #define ECORE_MAGIC_ANIMATOR 0xf7643ea5 +#define ECORE_MAGIC_POLLER 0xf7568127 #define ECORE_MAGIC Ecore_Magic __magic @@ -221,6 +222,11 @@ */ }; typedef enum _Ecore_Exe_Flags Ecore_Exe_Flags; +enum _Ecore_Poller_Type +{ + ECORE_POLLER_CORE = 0 +}; +typedef enum _Ecore_Poller_Type Ecore_Poller_Type; #ifndef _WIN32 typedef struct _Ecore_Exe Ecore_Exe; @@ -234,6 +240,7 @@ typedef struct _Ecore_Event_Filter Ecore_Event_Filter; typedef struct _Ecore_Event Ecore_Event; typedef struct _Ecore_Animator Ecore_Animator; +typedef struct _Ecore_Poller Ecore_Poller; #ifndef _WIN32 struct _Ecore_Exe @@ -371,6 +378,16 @@ void *data; }; +struct _Ecore_Poller +{ + Ecore_List2 __list_data; + ECORE_MAGIC; + int ibit; + signed char delete_me : 1; + int (*func) (void *data); + void *data; +}; + #endif EAPI void _ecore_magic_fail(void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname); @@ -422,7 +439,8 @@ void _ecore_animator_shutdown(void); - +void _ecore_poller_shutdown(void); + EAPI void *_ecore_list2_append (void *in_list, void *in_item); EAPI void *_ecore_list2_prepend (void *in_list, void *in_item); EAPI void *_ecore_list2_append_relative (void *in_list, void *in_item, void *in_relative); =================================================================== RCS file: /cvs/e/e17/libs/ecore/src/lib/ecore/ecore_timer.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -3 -r1.16 -r1.17 --- ecore_timer.c 28 Dec 2006 03:31:44 -0000 1.16 +++ ecore_timer.c 11 Jan 2008 07:33:56 -0000 1.17 @@ -153,10 +153,15 @@ { double now; double in; + Ecore_Timer *timer; if (!timers) return -1; now = ecore_time_get(); - in = timers->at - now; + timer = (Ecore_Timer *)timers; + while ((timer) && ((timer->delete_me) || (timer->just_added))) + timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next; + if (!timer) return -1; + in = timer->at - now; if (in < 0) in = 0; return in; } @@ -166,7 +171,7 @@ { Ecore_List2 *l; Ecore_Timer *timer; - + if (!timers) return 0; if (last_check > when) { @@ -189,13 +194,18 @@ _ecore_timer_call(when); if ((!timer->delete_me) && (timer->func(timer->data))) { - /* if the timer would have gone off more than 30 seconds ago, + /* if the timer would have gone off more than 15 seconds ago, * assume that the system hung and set the timer to go off - * timer->in from now. + * timer->in from now. this handles system hangs, suspends + * and more, so ecore will only "replay" the timers while + * the system is suspended if it is suspended for less than + * 15 seconds (basically). this also handles if the process + * is stopped in a debugger or IO and other handling gets + * really slow within the main loop. */ if (!timer->delete_me) { - if ((timer->at + timer->in) < (when - 30.0)) + if ((timer->at + timer->in) < (when - 15.0)) _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data); else _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data); |