X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/b6bd159922608fa474026837771d63bf7eadcf97..aea124c47dd16cde97fa467082b4be5f2c6d31f7:/src/xgselect.c diff --git a/src/xgselect.c b/src/xgselect.c index 339ec47511..a281414610 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -1,6 +1,6 @@ /* Function for handling the GLib event loop. -Copyright (C) 2009-2011 Free Software Foundation, Inc. +Copyright (C) 2009-2014 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -15,56 +15,58 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see . */ +along with GNU Emacs. If not, see . */ #include -#include #include "xgselect.h" -#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) +#ifdef HAVE_GLIB #include #include -#include - -static GPollFD *gfds; -static ptrdiff_t gfds_size; +#include +#include "frame.h" int -xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, - EMACS_TIME *timeout) +xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, + struct timespec const *timeout, sigset_t const *sigmask) { - SELECT_TYPE all_rfds, all_wfds; - EMACS_TIME tmo, *tmop = timeout; + fd_set all_rfds, all_wfds; + struct timespec tmo; + struct timespec const *tmop = timeout; - GMainContext *context = g_main_context_default (); + GMainContext *context; int have_wfds = wfds != NULL; - int n_gfds = 0, our_tmo = 0, retval = 0, our_fds = 0; + GPollFD gfds_buf[128]; + GPollFD *gfds = gfds_buf; + int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; + int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; int i, nfds, tmo_in_millisec; + USE_SAFE_ALLOCA; - if (rfds) memcpy (&all_rfds, rfds, sizeof (all_rfds)); - else FD_ZERO (&all_rfds); - if (wfds) memcpy (&all_wfds, wfds, sizeof (all_rfds)); - else FD_ZERO (&all_wfds); + /* Do not try to optimize with an initial check with g_main_context_pending + and a call to pselect if it returns false. If Gdk has a timeout for 0.01 + second, and Emacs has a timeout for 1 second, g_main_context_pending will + return false, but the timeout will be 1 second, thus missing the gdk + timeout with a lot. */ - /* Update event sources in GLib. */ - g_main_context_pending (context); + context = g_main_context_default (); - do { - if (n_gfds > gfds_size) - { - xfree (gfds); - gfds = xpalloc (0, &gfds_size, n_gfds - gfds_size, INT_MAX, - sizeof *gfds); - } + if (rfds) all_rfds = *rfds; + else FD_ZERO (&all_rfds); + if (wfds) all_wfds = *wfds; + else FD_ZERO (&all_wfds); - n_gfds = g_main_context_query (context, - G_PRIORITY_LOW, - &tmo_in_millisec, - gfds, - gfds_size); - } while (n_gfds > gfds_size); + n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, + gfds, gfds_size); + if (gfds_size < n_gfds) + { + SAFE_NALLOCA (gfds, sizeof *gfds, n_gfds); + gfds_size = n_gfds; + n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, + gfds, gfds_size); + } for (i = 0; i < n_gfds; ++i) { @@ -81,30 +83,25 @@ xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, } } + SAFE_FREE (); + if (tmo_in_millisec >= 0) { - EMACS_SET_SECS_USECS (tmo, tmo_in_millisec/1000, - 1000 * (tmo_in_millisec % 1000)); - if (!timeout) our_tmo = 1; - else - { - EMACS_TIME difference; - - EMACS_SUB_TIME (difference, tmo, *timeout); - if (EMACS_TIME_NEG_P (difference)) our_tmo = 1; - } - - if (our_tmo) tmop = &tmo; + tmo = make_timespec (tmo_in_millisec / 1000, + 1000 * 1000 * (tmo_in_millisec % 1000)); + if (!timeout || timespec_cmp (tmo, *timeout) < 0) + tmop = &tmo; } - nfds = select (max_fds+1, &all_rfds, have_wfds ? &all_wfds : NULL, - efds, tmop); + fds_lim = max_fds + 1; + nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, + efds, tmop, sigmask); if (nfds < 0) retval = nfds; else if (nfds > 0) { - for (i = 0; i < max_fds+1; ++i) + for (i = 0; i < fds_lim; ++i) { if (FD_ISSET (i, &all_rfds)) { @@ -127,34 +124,21 @@ xg_select (int max_fds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, } } - if (our_fds > 0 || (nfds == 0 && our_tmo)) - { - - /* If Gtk+ is in use eventually gtk_main_iteration will be called, - unless retval is zero. */ + /* If Gtk+ is in use eventually gtk_main_iteration will be called, + unless retval is zero. */ #ifdef USE_GTK - if (retval == 0) + if (retval == 0) #endif - while (g_main_context_pending (context)) - g_main_context_dispatch (context); + while (g_main_context_pending (context)) + g_main_context_dispatch (context); - /* To not have to recalculate timeout, return like this. */ - if (retval == 0) - { - retval = -1; - errno = EINTR; - } + /* To not have to recalculate timeout, return like this. */ + if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) + { + retval = -1; + errno = EINTR; } return retval; } -#endif /* USE_GTK || HAVE_GCONF || HAVE_GSETTINGS */ - -void -xgselect_initialize (void) -{ -#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS) - gfds_size = 128; - gfds = xmalloc (sizeof (*gfds)*gfds_size); -#endif -} +#endif /* HAVE_GLIB */