]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/tty/lib_twait.c
ncurses 5.0
[ncurses.git] / ncurses / tty / lib_twait.c
similarity index 54%
rename from ncurses/lib_twait.c
rename to ncurses/tty/lib_twait.c
index 93f24d72488956d2e40cf244a40eb22a1884e974..f095c9b53c0c8c5e6c04c7ab56b764d14bb131f5 100644 (file)
 **     comments, none of the original code remains - T.Dickey).
 */
 
+#ifdef __BEOS__
+#include <OS.h>
+#endif
+
 #include <curses.priv.h>
 
 #if USE_FUNC_POLL
 # endif
 #endif
 
-#ifdef __BEOS__
-/* BeOS select() only works on sockets.  Use the tty hack instead */
-#include <socket.h>
-#define select check_select
-#endif
-
-MODULE_ID("$Id: lib_twait.c,v 1.30 1998/02/11 12:14:01 tom Exp $")
+MODULE_ID("$Id: lib_twait.c,v 1.34 1999/10/16 21:25:10 tom Exp $")
 
-/*
- * We want to define GOOD_SELECT if the last argument of select(2) is
- * modified to indicate time left.  The code will deal gracefully with
- * the other case, this is just an optimization to reduce the number
- * of system calls per input event.
- *
- * In general, expect System-V-like UNIXes to have this behavior and BSD-like
- * ones to not have it.  Check your manual page.  If it doesn't explicitly
- * say the last argument is modified, assume it's not.
- *
- * (We'd really like configure to autodetect this, but writing a proper test
- * turns out to be hard.)
- */
+static long _nc_gettime(bool first)
+{
+       long res;
 
 #if HAVE_GETTIMEOFDAY
-#if (defined(TRACE) && !HAVE_USLEEP) || ! GOOD_SELECT
-static void _nc_gettime(struct timeval *tp)
-{
-       gettimeofday(tp, (struct timezone *)0);
-       T(("time: %ld.%06ld", (long) tp->tv_sec, (long) tp->tv_usec));
-}
-#endif
+# define PRECISE_GETTIME 1
+       static struct timeval t0;
+       struct timeval t1;
+       gettimeofday(&t1, (struct timezone *)0);
+       if (first) {
+               t0 = t1;
+       }
+       res = (t1.tv_sec  - t0.tv_sec)  * 1000
+           + (t1.tv_usec - t0.tv_usec) / 1000;
+#else
+# define PRECISE_GETTIME 0
+       static time_t t0;
+       time_t t1 = time((time_t*)0);
+       if (first) {
+               t0 = t1;
+       }
+       res = (t1 - t0) * 1000;
 #endif
+       T(("%s time: %ld msec", first ? "get" : "elapsed", res));
+       return res;
+}
 
 /*
  * Wait a specified number of milliseconds, returning nonzero if the timer
@@ -105,132 +106,128 @@ static void _nc_gettime(struct timeval *tp)
 int _nc_timed_wait(int mode, int milliseconds, int *timeleft)
 {
 int    fd;
-int    count = 0;
-long   whole_secs = milliseconds / 1000;
-long   micro_secs = (milliseconds % 1000) * 1000;
+int    count;
 
-int result = 0;
-struct timeval ntimeout;
+int result;
 
 #if USE_FUNC_POLL
 struct pollfd fds[2];
+#elif defined(__BEOS__)
 #elif HAVE_SELECT
 static fd_set set;
 #endif
 
-#if !GOOD_SELECT && HAVE_GETTIMEOFDAY
-struct timeval starttime, returntime;
-long delta;
+long starttime, returntime;
+
+       T(("start twait: %d milliseconds, mode: %d", milliseconds, mode));
 
-       _nc_gettime(&starttime);
+#if PRECISE_GETTIME
+retry:
 #endif
+       starttime = _nc_gettime(TRUE);
 
-       if (milliseconds >= 0) {
-               ntimeout.tv_sec  = whole_secs;
-               ntimeout.tv_usec = micro_secs;
-       } else {
-               ntimeout.tv_sec  = 0;
-               ntimeout.tv_usec = 0;
-       }
+       count = 0;
 
-       T(("start twait: %lu.%06lu secs, mode: %d", (long) ntimeout.tv_sec, (long) ntimeout.tv_usec, mode));
+#if USE_FUNC_POLL
+       if (mode & 1) {
+               fds[count].fd     = SP->_ifd;
+               fds[count].events = POLLIN;
+               count++;
+       }
+       if ((mode & 2)
+        && (fd = SP->_mouse_fd) >= 0) {
+               fds[count].fd     = fd;
+               fds[count].events = POLLIN;
+               count++;
+       }
+       result = poll(fds, count, milliseconds);
 
-#ifdef HIDE_EINTR
+#elif defined(__BEOS__)
        /*
-        * The do loop tries to make it look like we have restarting signals,
-        * even if we don't.
+        * BeOS's select() is declared in socket.h, so the configure script does
+        * not see it.  That's just as well, since that function works only for
+        * sockets.  This (using snooze and ioctl) was distilled from Be's patch
+        * for ncurses which uses a separate thread to simulate select().
+        *
+        * FIXME: the return values from the ioctl aren't very clear if we get
+        * interrupted.
         */
-       do {
-#endif /* HIDE_EINTR */
-#if !GOOD_SELECT && HAVE_GETTIMEOFDAY
-       retry:
-#endif
-               count = 0;
-#if USE_FUNC_POLL
+       result = 0;
+       if (mode & 1) {
+               bigtime_t d;
+               bigtime_t useconds = milliseconds * 1000;
+               int n, howmany;
 
-               if (mode & 1) {
-                       fds[count].fd     = SP->_ifd;
-                       fds[count].events = POLLIN;
-                       count++;
-               }
-               if ((mode & 2)
-                && (fd = SP->_mouse_fd) >= 0) {
-                       fds[count].fd     = fd;
-                       fds[count].events = POLLIN;
-                       count++;
+               if (useconds == 0) /* we're here to go _through_ the loop */
+                       useconds = 1;
+
+               for (d = 0; d < useconds; d += 5000) {
+                       n = 0;
+                       howmany = ioctl(0, 'ichr', &n);
+                       if (howmany >= 0 && n > 0) {
+                               result = 1;
+                               break;
+                       }
+                       if (useconds > 1)
+                               snooze(5000);
+                       milliseconds -= 5;
                }
-               result = poll(fds, count, milliseconds);
+       } else if (milliseconds > 0) {
+               snooze(milliseconds * 1000);
+               milliseconds = 0;
+       }
 #elif HAVE_SELECT
-               /*
-                * Some systems modify the fd_set arguments; do this in the
-                * loop.
-                */
-               FD_ZERO(&set);
+       /*
+        * select() modifies the fd_set arguments; do this in the
+        * loop.
+        */
+       FD_ZERO(&set);
 
-               if (mode & 1) {
-                       FD_SET(SP->_ifd, &set);
-                       count = SP->_ifd + 1;
-               }
-               if ((mode & 2)
-                && (fd = SP->_mouse_fd) >= 0) {
-                       FD_SET(fd, &set);
-                       count = max(fd, count) + 1;
-               }
+       if (mode & 1) {
+               FD_SET(SP->_ifd, &set);
+               count = SP->_ifd + 1;
+       }
+       if ((mode & 2)
+        && (fd = SP->_mouse_fd) >= 0) {
+               FD_SET(fd, &set);
+               count = max(fd, count) + 1;
+       }
 
-               errno = 0;
-               result = select(count, &set, NULL, NULL, milliseconds >= 0 ? &ntimeout : 0);
+       if (milliseconds >= 0) {
+               struct timeval ntimeout;
+               ntimeout.tv_sec  = milliseconds / 1000;
+               ntimeout.tv_usec = (milliseconds % 1000) * 1000;
+               result = select(count, &set, NULL, NULL, &ntimeout);
+       } else {
+               result = select(count, &set, NULL, NULL, NULL);
+       }
 #endif
 
-#if !GOOD_SELECT && HAVE_GETTIMEOFDAY
-               _nc_gettime(&returntime);
-
-               /* The contents of ntimeout aren't guaranteed after return from
-                * 'select()', so we disregard its contents.  Also, note that
-                * on some systems, tv_sec and tv_usec are unsigned.
-                */
-               ntimeout.tv_sec  = whole_secs;
-               ntimeout.tv_usec = micro_secs;
-
-#define DELTA(f) (long)ntimeout.f - (long)returntime.f + (long)starttime.f
-
-               delta = DELTA(tv_sec);
-               if (delta < 0)
-                       delta = 0;
-               ntimeout.tv_sec = delta;
+       returntime = _nc_gettime(FALSE);
 
-               delta = DELTA(tv_usec);
-               while (delta < 0 && ntimeout.tv_sec != 0) {
-                       ntimeout.tv_sec--;
-                       delta += 1000000;
-               }
-               ntimeout.tv_usec = delta;
-               if (delta < 0)
-                       ntimeout.tv_sec = ntimeout.tv_usec = 0;
+       if (milliseconds >= 0)
+               milliseconds -= (returntime - starttime);
 
-               /*
-                * If the timeout hasn't expired, and we've gotten no data,
-                * this is probably a system where 'select()' needs to be left
-                * alone so that it can complete.  Make this process sleep,
-                * then come back for more.
-                */
-               if (result == 0
-                && (ntimeout.tv_sec != 0 || ntimeout.tv_usec > 100000)) {
-                       napms(100);
-                       goto retry;
-               }
-#endif
-#ifdef HIDE_EINTR
-       } while (result == -1 && errno == EINTR);
+#if PRECISE_GETTIME
+       /*
+        * If the timeout hasn't expired, and we've gotten no data,
+        * this is probably a system where 'select()' needs to be left
+        * alone so that it can complete.  Make this process sleep,
+        * then come back for more.
+        */
+       if (result == 0 && milliseconds > 100) {
+               napms(100);
+               milliseconds -= 100;
+               goto retry;
+       }
 #endif
 
-       /* return approximate time left on the ntimeout, in milliseconds */
+       /* return approximate time left in milliseconds */
        if (timeleft)
-               *timeleft = (ntimeout.tv_sec * 1000) + (ntimeout.tv_usec / 1000);
+               *timeleft = milliseconds;
 
-       T(("end twait: returned %d (%d), remaining time %lu.%06lu secs (%d msec)",
-               result, errno,
-               (long) ntimeout.tv_sec, (long) (ntimeout.tv_usec / 1000),
-               timeleft ? *timeleft : -1));
+       T(("end twait: returned %d (%d), remaining time %d msec",
+               result, errno, milliseconds));
 
        /*
         * Both 'poll()' and 'select()' return the number of file descriptors
@@ -249,6 +246,8 @@ long delta;
                                        count++;
                                }
                        }
+#elif defined(__BEOS__)
+                       result = 1;     /* redundant, but simple */
 #elif HAVE_SELECT
                        if ((mode & 2)
                         && (fd = SP->_mouse_fd) >= 0