lib_twait.c revision 66963
150276Speter/**************************************************************************** 262449Speter * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 3250276Speter ****************************************************************************/ 3350276Speter 3450276Speter/* 3550276Speter** lib_twait.c 3650276Speter** 3750276Speter** The routine _nc_timed_wait(). 3850276Speter** 3950276Speter** (This file was originally written by Eric Raymond; however except for 4050276Speter** comments, none of the original code remains - T.Dickey). 4150276Speter*/ 4250276Speter 4356639Speter#ifdef __BEOS__ 4456639Speter#include <OS.h> 4556639Speter#endif 4656639Speter 4750276Speter#include <curses.priv.h> 4850276Speter 4950276Speter#if USE_FUNC_POLL 5050276Speter# if HAVE_SYS_TIME_H 5150276Speter# include <sys/time.h> 5250276Speter# endif 5350276Speter#elif HAVE_SELECT 5450276Speter# if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT 5550276Speter# include <sys/time.h> 5650276Speter# endif 5750276Speter# if HAVE_SYS_SELECT_H 5850276Speter# include <sys/select.h> 5950276Speter# endif 6050276Speter#endif 6150276Speter 6266963SpeterMODULE_ID("$Id: lib_twait.c,v 1.39 2000/08/26 19:34:15 tom Exp $") 6350276Speter 6466963Speterstatic long 6566963Speter_nc_gettime(bool first) 6650276Speter{ 6766963Speter long res; 6850276Speter 6950276Speter#if HAVE_GETTIMEOFDAY 7050276Speter# define PRECISE_GETTIME 1 7166963Speter static struct timeval t0; 7266963Speter struct timeval t1; 7366963Speter gettimeofday(&t1, (struct timezone *) 0); 7466963Speter if (first) { 7566963Speter t0 = t1; 7666963Speter } 7766963Speter res = (t1.tv_sec - t0.tv_sec) * 1000 7866963Speter + (t1.tv_usec - t0.tv_usec) / 1000; 7950276Speter#else 8050276Speter# define PRECISE_GETTIME 0 8166963Speter static time_t t0; 8266963Speter time_t t1 = time((time_t *) 0); 8366963Speter if (first) { 8466963Speter t0 = t1; 8566963Speter } 8666963Speter res = (t1 - t0) * 1000; 8750276Speter#endif 8866963Speter T(("%s time: %ld msec", first ? "get" : "elapsed", res)); 8966963Speter return res; 9050276Speter} 9150276Speter 9250276Speter/* 9350276Speter * Wait a specified number of milliseconds, returning nonzero if the timer 9450276Speter * didn't expire before there is activity on the specified file descriptors. 9550276Speter * The file-descriptors are specified by the mode: 9650276Speter * 0 - none (absolute time) 9750276Speter * 1 - ncurses' normal input-descriptor 9850276Speter * 2 - mouse descriptor, if any 9950276Speter * 3 - either input or mouse. 10050276Speter * We return a mask that corresponds to the mode (e.g., 2 for mouse activity). 10150276Speter * 10250276Speter * If the milliseconds given are -1, the wait blocks until activity on the 10350276Speter * descriptors. 10450276Speter */ 10566963Speterint 10666963Speter_nc_timed_wait(int mode, int milliseconds, int *timeleft) 10750276Speter{ 10866963Speter int fd; 10966963Speter int count; 11050276Speter 11166963Speter int result; 11250276Speter 11350276Speter#if USE_FUNC_POLL 11466963Speter struct pollfd fds[2]; 11556639Speter#elif defined(__BEOS__) 11650276Speter#elif HAVE_SELECT 11766963Speter static fd_set set; 11850276Speter#endif 11950276Speter 12066963Speter long starttime, returntime; 12150276Speter 12266963Speter T(("start twait: %d milliseconds, mode: %d", milliseconds, mode)); 12350276Speter 12450276Speter#if PRECISE_GETTIME 12566963Speter retry: 12650276Speter#endif 12766963Speter starttime = _nc_gettime(TRUE); 12850276Speter 12966963Speter count = 0; 13050276Speter 13150276Speter#if USE_FUNC_POLL 13266963Speter memset(fds, 0, sizeof(fds)); 13366963Speter if (mode & 1) { 13466963Speter fds[count].fd = SP->_ifd; 13566963Speter fds[count].events = POLLIN; 13666963Speter count++; 13766963Speter } 13866963Speter if ((mode & 2) 13966963Speter && (fd = SP->_mouse_fd) >= 0) { 14066963Speter fds[count].fd = fd; 14166963Speter fds[count].events = POLLIN; 14266963Speter count++; 14366963Speter } 14466963Speter result = poll(fds, count, milliseconds); 14550276Speter 14656639Speter#elif defined(__BEOS__) 14766963Speter /* 14866963Speter * BeOS's select() is declared in socket.h, so the configure script does 14966963Speter * not see it. That's just as well, since that function works only for 15066963Speter * sockets. This (using snooze and ioctl) was distilled from Be's patch 15166963Speter * for ncurses which uses a separate thread to simulate select(). 15266963Speter * 15366963Speter * FIXME: the return values from the ioctl aren't very clear if we get 15466963Speter * interrupted. 15566963Speter */ 15666963Speter result = 0; 15766963Speter if (mode & 1) { 15866963Speter bigtime_t d; 15966963Speter bigtime_t useconds = milliseconds * 1000; 16066963Speter int n, howmany; 16156639Speter 16266963Speter if (useconds == 0) /* we're here to go _through_ the loop */ 16366963Speter useconds = 1; 16456639Speter 16566963Speter for (d = 0; d < useconds; d += 5000) { 16666963Speter n = 0; 16766963Speter howmany = ioctl(0, 'ichr', &n); 16866963Speter if (howmany >= 0 && n > 0) { 16966963Speter result = 1; 17066963Speter break; 17166963Speter } 17266963Speter if (useconds > 1) 17366963Speter snooze(5000); 17466963Speter milliseconds -= 5; 17556639Speter } 17666963Speter } else if (milliseconds > 0) { 17766963Speter snooze(milliseconds * 1000); 17866963Speter milliseconds = 0; 17966963Speter } 18050276Speter#elif HAVE_SELECT 18166963Speter /* 18266963Speter * select() modifies the fd_set arguments; do this in the 18366963Speter * loop. 18466963Speter */ 18566963Speter FD_ZERO(&set); 18650276Speter 18766963Speter if (mode & 1) { 18866963Speter FD_SET(SP->_ifd, &set); 18966963Speter count = SP->_ifd + 1; 19066963Speter } 19166963Speter if ((mode & 2) 19266963Speter && (fd = SP->_mouse_fd) >= 0) { 19366963Speter FD_SET(fd, &set); 19466963Speter count = max(fd, count) + 1; 19566963Speter } 19650276Speter 19766963Speter if (milliseconds >= 0) { 19866963Speter struct timeval ntimeout; 19966963Speter ntimeout.tv_sec = milliseconds / 1000; 20066963Speter ntimeout.tv_usec = (milliseconds % 1000) * 1000; 20166963Speter result = select(count, &set, NULL, NULL, &ntimeout); 20266963Speter } else { 20366963Speter result = select(count, &set, NULL, NULL, NULL); 20466963Speter } 20550276Speter#endif 20650276Speter 20766963Speter returntime = _nc_gettime(FALSE); 20850276Speter 20966963Speter if (milliseconds >= 0) 21066963Speter milliseconds -= (returntime - starttime); 21150276Speter 21250276Speter#if PRECISE_GETTIME 21366963Speter /* 21466963Speter * If the timeout hasn't expired, and we've gotten no data, 21566963Speter * this is probably a system where 'select()' needs to be left 21666963Speter * alone so that it can complete. Make this process sleep, 21766963Speter * then come back for more. 21866963Speter */ 21966963Speter if (result == 0 && milliseconds > 100) { 22066963Speter napms(100); 22166963Speter milliseconds -= 100; 22266963Speter goto retry; 22366963Speter } 22450276Speter#endif 22550276Speter 22666963Speter /* return approximate time left in milliseconds */ 22766963Speter if (timeleft) 22866963Speter *timeleft = milliseconds; 22950276Speter 23066963Speter T(("end twait: returned %d (%d), remaining time %d msec", 23166963Speter result, errno, milliseconds)); 23250276Speter 23366963Speter /* 23466963Speter * Both 'poll()' and 'select()' return the number of file descriptors 23566963Speter * that are active. Translate this back to the mask that denotes which 23666963Speter * file-descriptors, so that we don't need all of this system-specific 23766963Speter * code everywhere. 23866963Speter */ 23966963Speter if (result != 0) { 24066963Speter if (result > 0) { 24166963Speter result = 0; 24250276Speter#if USE_FUNC_POLL 24366963Speter for (count = 0; count < 2; count++) { 24466963Speter if ((mode & (1 << count)) 24566963Speter && (fds[count].revents & POLLIN)) { 24666963Speter result |= (1 << count); 24766963Speter } 24866963Speter } 24956639Speter#elif defined(__BEOS__) 25066963Speter result = 1; /* redundant, but simple */ 25150276Speter#elif HAVE_SELECT 25266963Speter if ((mode & 2) 25366963Speter && (fd = SP->_mouse_fd) >= 0 25466963Speter && FD_ISSET(fd, &set)) 25566963Speter result |= 2; 25666963Speter if ((mode & 1) 25766963Speter && FD_ISSET(SP->_ifd, &set)) 25866963Speter result |= 1; 25950276Speter#endif 26066963Speter } else 26166963Speter result = 0; 26266963Speter } 26350276Speter 26466963Speter return (result); 26550276Speter} 266