Added support for using select() instead of poll().

This commit is contained in:
crs 2002-10-16 22:01:50 +00:00
parent c1797c6867
commit 11e29ff7eb
6 changed files with 301 additions and 157 deletions

View File

@ -75,6 +75,21 @@ AC_DEFUN([ACX_CHECK_CXX_STDLIB], [
fi fi
])dnl ACX_CHECK_CXX_STDLIB ])dnl ACX_CHECK_CXX_STDLIB
AC_DEFUN([ACX_CHECK_POLL], [
AC_MSG_CHECKING([for poll])
AC_TRY_LINK([#include <sys/poll.h>],
[struct pollfd ufds[] = { 0, POLLIN, 0 }; poll(ufds, 1, 10);],
acx_poll_ok=yes, acx_poll_ok=no)
AC_MSG_RESULT($acx_poll_ok)
if test x"$acx_poll_ok" = xyes; then
ifelse([$1],,AC_DEFINE(HAVE_POLL,1,[Define if you have the `poll' function.]),[$1])
:
else
acx_poll_ok=no
$2
fi
])dnl ACX_CHECK_POLL
dnl The following macros are from http://www.gnu.org/software/ac-archive/ dnl The following macros are from http://www.gnu.org/software/ac-archive/
dnl which distributes them under the following license: dnl which distributes them under the following license:
dnl dnl

View File

@ -72,6 +72,8 @@ AC_FUNC_STRFTIME
AC_CHECK_FUNCS(gmtime_r) AC_CHECK_FUNCS(gmtime_r)
AC_CHECK_FUNCS(getpwuid_r) AC_CHECK_FUNCS(getpwuid_r)
AC_CHECK_FUNCS(vsnprintf) AC_CHECK_FUNCS(vsnprintf)
AC_FUNC_SELECT_ARGTYPES
ACX_CHECK_POLL
dnl use AC_REPLACE_FUNCS() for stuff in string.h dnl use AC_REPLACE_FUNCS() for stuff in string.h
dnl checks for system services dnl checks for system services

View File

@ -51,6 +51,7 @@ struct protoent FAR * (PASCAL FAR *CNetwork::getprotobyname)(const char FAR * na
int (PASCAL FAR *CNetwork::getsockerror)(void); int (PASCAL FAR *CNetwork::getsockerror)(void);
int (PASCAL FAR *CNetwork::gethosterror)(void); int (PASCAL FAR *CNetwork::gethosterror)(void);
int (PASCAL FAR *CNetwork::setblocking)(CNetwork::Socket s, bool blocking); int (PASCAL FAR *CNetwork::setblocking)(CNetwork::Socket s, bool blocking);
int (PASCAL FAR *CNetwork::setnodelay)(CNetwork::Socket s, bool blocking);
#if WINDOWS_LIKE #if WINDOWS_LIKE
@ -226,79 +227,11 @@ CNetwork::init2(
read = read2; read = read2;
write = write2; write = write2;
setblocking = setblocking2; setblocking = setblocking2;
setnodelay = setnodelay2;
s_networkModule = module; s_networkModule = module;
} }
int PASCAL FAR
CNetwork::poll2(PollEntry fd[], int nfds, int timeout)
{
int i;
// prepare sets for select
fd_set readSet, writeSet, errSet;
fd_set* readSetP = NULL;
fd_set* writeSetP = NULL;
fd_set* errSetP = NULL;
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&errSet);
for (i = 0; i < nfds; ++i) {
if (fd[i].events & kPOLLIN) {
FD_SET(fd[i].fd, &readSet);
readSetP = &readSet;
}
if (fd[i].events & kPOLLOUT) {
FD_SET(fd[i].fd, &writeSet);
writeSetP = &writeSet;
}
if (true) {
FD_SET(fd[i].fd, &errSet);
errSetP = &errSet;
}
}
// prepare timeout for select
struct timeval timeout2;
struct timeval* timeout2P;
if (timeout < 0) {
timeout2P = NULL;
}
else {
timeout2P = &timeout2;
timeout2.tv_sec = timeout / 1000;
timeout2.tv_usec = 1000 * (timeout % 1000);
}
// do the select. note that winsock ignores the first argument.
int n = select(0, readSetP, writeSetP, errSetP, timeout2P);
// handle results
if (n == Error) {
return Error;
}
if (n == 0) {
return 0;
}
n = 0;
for (i = 0; i < nfds; ++i) {
fd[i].revents = 0;
if (FD_ISSET(fd[i].fd, &readSet)) {
fd[i].revents |= kPOLLIN;
}
if (FD_ISSET(fd[i].fd, &writeSet)) {
fd[i].revents |= kPOLLOUT;
}
if (FD_ISSET(fd[i].fd, &errSet)) {
fd[i].revents |= kPOLLERR;
}
if (fd[i].revents != 0) {
++n;
}
}
return n;
}
ssize_t PASCAL FAR ssize_t PASCAL FAR
CNetwork::read2(Socket s, void FAR* buf, size_t len) CNetwork::read2(Socket s, void FAR* buf, size_t len)
{ {
@ -318,17 +251,39 @@ CNetwork::setblocking2(CNetwork::Socket s, bool blocking)
return ioctl(s, FIONBIO, &flag); return ioctl(s, FIONBIO, &flag);
} }
int PASCAL FAR
CNetwork::setnodelay2(CNetwork::Socket s, bool nodelay)
{
BOOL flag = nodelay ? 1 : 0;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
}
#endif #endif
#if UNIX_LIKE #if UNIX_LIKE
#include <unistd.h> #if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#if !defined(TCP_NODELAY) || !defined(SOL_TCP)
# include <netinet/tcp.h>
#endif
// FIXME -- use reentrant versions of non-reentrant functions // FIXME -- use reentrant versions of non-reentrant functions
const int CNetwork::Error = -1;
const CNetwork::Socket CNetwork::Null = -1;
#define setfunc(var, name, type) var = (type)::name #define setfunc(var, name, type) var = (type)::name
UInt32 UInt32
@ -355,30 +310,73 @@ CNetwork::swapntohs(UInt16 v)
return ntohs(v); return ntohs(v);
} }
static void
int CNetwork::init()
myerrno() {
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen));
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen));
setfunc(close, close, int (PASCAL FAR *)(Socket s));
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
setfunc(ioctl, ioctl, int (PASCAL FAR *)(Socket s, int cmd, void FAR *));
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog));
#if HAVE_POLL
setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
#else
setfunc(poll, CNetwork::poll2, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout));
#endif
setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len));
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen));
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags));
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen));
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen));
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how));
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol));
setfunc(write, write, ssize_t (PASCAL FAR *)(CNetwork::Socket s, const void FAR * buf, size_t len));
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto));
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto));
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name));
gethostname = gethostname2;
getsockerror = getsockerror2;
gethosterror = gethosterror2;
setblocking = setblocking2;
setnodelay = setnodelay2;
}
void
CNetwork::cleanup()
{
// do nothing
}
int PASCAL FAR
CNetwork::gethostname2(char* name, int namelen)
{
return ::gethostname(name, namelen);
}
int PASCAL FAR
CNetwork::getsockerror2(void)
{ {
return errno; return errno;
} }
static int PASCAL FAR
int CNetwork::gethosterror2(void)
myherrno()
{ {
return h_errno; return h_errno;
} }
static int PASCAL FAR
int CNetwork::setblocking2(CNetwork::Socket s, bool blocking)
mygethostname(char* name, int namelen)
{
return gethostname(name, namelen);
}
static
int
mysetblocking(CNetwork::Socket s, bool blocking)
{ {
int mode = fcntl(s, F_GETFL, 0); int mode = fcntl(s, F_GETFL, 0);
if (mode == -1) { if (mode == -1) {
@ -396,49 +394,111 @@ mysetblocking(CNetwork::Socket s, bool blocking)
return 0; return 0;
} }
const int CNetwork::Error = -1; int PASCAL FAR
const CNetwork::Socket CNetwork::Null = -1; CNetwork::setnodelay2(CNetwork::Socket s, bool nodelay)
void
CNetwork::init()
{ {
setfunc(accept, accept, Socket (PASCAL FAR *)(Socket s, Address FAR *addr, AddressLength FAR *addrlen)); int flag = nodelay ? 1 : 0;
setfunc(bind, bind, int (PASCAL FAR *)(Socket s, const Address FAR *addr, AddressLength namelen)); setsockopt(s, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
setfunc(close, close, int (PASCAL FAR *)(Socket s)); }
setfunc(connect, connect, int (PASCAL FAR *)(Socket s, const Address FAR *name, AddressLength namelen));
setfunc(ioctl, ioctl, int (PASCAL FAR *)(Socket s, int cmd, void FAR *)); #endif
setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen));
setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen)); #if WINDOWS_LIKE || !HAVE_POLL
setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen));
setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp)); #if HAVE_SYS_SELECT_H
setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in)); # include <sys/select.h>
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog)); #endif
setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout)); #if HAVE_SYS_TIME_H
setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len)); # include <sys/time.h>
setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags)); #endif
setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen)); #if HAVE_SYS_TYPES_H
setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags)); # include <sys/types.h>
setfunc(sendto, sendto, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags, const Address FAR *to, AddressLength tolen)); #endif
setfunc(setsockopt, setsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, const void FAR * optval, AddressLength optlen)); #if HAVE_UNISTD_H
setfunc(shutdown, shutdown, int (PASCAL FAR *)(Socket s, int how)); # include <unistd.h>
setfunc(socket, socket, Socket (PASCAL FAR *)(int af, int type, int protocol)); #endif
setfunc(write, write, ssize_t (PASCAL FAR *)(CNetwork::Socket s, const void FAR * buf, size_t len));
setfunc(gethostbyaddr, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type)); int PASCAL FAR
setfunc(gethostbyname, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name)); CNetwork::poll2(PollEntry fd[], int nfds, int timeout)
setfunc(gethostname, mygethostname, int (PASCAL FAR *)(char FAR * name, int namelen)); {
setfunc(getservbyport, getservbyport, struct servent FAR * (PASCAL FAR *)(int port, const char FAR * proto)); int i;
setfunc(getservbyname, getservbyname, struct servent FAR * (PASCAL FAR *)(const char FAR * name, const char FAR * proto));
setfunc(getprotobynumber, getprotobynumber, struct protoent FAR * (PASCAL FAR *)(int proto)); // prepare sets for select
setfunc(getprotobyname, getprotobyname, struct protoent FAR * (PASCAL FAR *)(const char FAR * name)); int n = 0;
setfunc(getsockerror, myerrno, int (PASCAL FAR *)(void)); fd_set readSet, writeSet, errSet;
setfunc(gethosterror, myherrno, int (PASCAL FAR *)(void)); fd_set* readSetP = NULL;
setfunc(setblocking, mysetblocking, int (PASCAL FAR *)(Socket, bool)); fd_set* writeSetP = NULL;
} fd_set* errSetP = NULL;
FD_ZERO(&readSet);
void FD_ZERO(&writeSet);
CNetwork::cleanup() FD_ZERO(&errSet);
{ for (i = 0; i < nfds; ++i) {
// do nothing if (fd[i].events & kPOLLIN) {
FD_SET(fd[i].fd, &readSet);
readSetP = &readSet;
if (fd[i].fd > n) {
n = fd[i].fd;
}
}
if (fd[i].events & kPOLLOUT) {
FD_SET(fd[i].fd, &writeSet);
writeSetP = &writeSet;
if (fd[i].fd > n) {
n = fd[i].fd;
}
}
if (true) {
FD_SET(fd[i].fd, &errSet);
errSetP = &errSet;
if (fd[i].fd > n) {
n = fd[i].fd;
}
}
}
// prepare timeout for select
struct timeval timeout2;
struct timeval* timeout2P;
if (timeout < 0) {
timeout2P = NULL;
}
else {
timeout2P = &timeout2;
timeout2.tv_sec = timeout / 1000;
timeout2.tv_usec = 1000 * (timeout % 1000);
}
// do the select. note that winsock ignores the first argument.
n = select((SELECT_TYPE_ARG1) n + 1,
SELECT_TYPE_ARG234 readSetP,
SELECT_TYPE_ARG234 writeSetP,
SELECT_TYPE_ARG234 errSetP,
SELECT_TYPE_ARG5 timeout2P);
// handle results
if (n == Error) {
return Error;
}
if (n == 0) {
return 0;
}
n = 0;
for (i = 0; i < nfds; ++i) {
fd[i].revents = 0;
if (FD_ISSET(fd[i].fd, &readSet)) {
fd[i].revents |= kPOLLIN;
}
if (FD_ISSET(fd[i].fd, &writeSet)) {
fd[i].revents |= kPOLLOUT;
}
if (FD_ISSET(fd[i].fd, &errSet)) {
fd[i].revents |= kPOLLERR;
}
if (fd[i].revents != 0) {
++n;
}
}
return n;
} }
#endif #endif

View File

@ -17,15 +17,22 @@
#include "BasicTypes.h" #include "BasicTypes.h"
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#if HAVE_POLL
# include <sys/poll.h>
#endif
#if WINDOWS_LIKE #if WINDOWS_LIKE
// declare no functions in winsock2 // declare no functions in winsock2
# define INCL_WINSOCK_API_PROTOTYPES 0 # define INCL_WINSOCK_API_PROTOTYPES 0
# define INCL_WINSOCK_API_TYPEDEFS 0 # define INCL_WINSOCK_API_TYPEDEFS 0
# include <winsock2.h> # include <winsock2.h>
typedef int ssize_t; typedef int ssize_t;
# if !defined(SOL_TCP)
# define SOL_TCP IPPROTO_TCP
# endif
#else #else
# undef FAR # undef FAR
# undef PASCAL # undef PASCAL
@ -34,15 +41,8 @@ typedef int ssize_t;
#endif #endif
#if UNIX_LIKE #if UNIX_LIKE
# include <sys/types.h> # include <netdb.h>
# include <sys/poll.h> # include <errno.h>
# include <sys/socket.h>
# include <netdb.h>
# include <netinet/in.h>
# include <errno.h>
# if !defined(TCP_NODELAY) || !defined(SOL_TCP)
# include <netinet/tcp.h>
# endif
#endif #endif
//! Networking functions //! Networking functions
@ -53,7 +53,13 @@ public:
typedef SOCKET Socket; typedef SOCKET Socket;
typedef struct sockaddr Address; typedef struct sockaddr Address;
typedef int AddressLength; typedef int AddressLength;
typedef BOOL TCPNoDelayType; #elif UNIX_LIKE
typedef int Socket;
typedef struct sockaddr Address;
typedef socklen_t AddressLength;
#endif
#if WINDOWS_LIKE || !HAVE_POLL
class PollEntry { class PollEntry {
public: public:
Socket fd; Socket fd;
@ -61,21 +67,17 @@ public:
short revents; short revents;
}; };
enum { enum {
kPOLLIN = 1, kPOLLIN = 1,
kPOLLOUT = 2, kPOLLOUT = 2,
kPOLLERR = 4, kPOLLERR = 4,
kPOLLNVAL = 8 kPOLLNVAL = 8
}; };
#elif UNIX_LIKE #else
typedef int Socket;
typedef struct sockaddr Address;
typedef socklen_t AddressLength;
typedef struct pollfd PollEntry; typedef struct pollfd PollEntry;
typedef int TCPNoDelayType;
enum { enum {
kPOLLIN = POLLIN, kPOLLIN = POLLIN,
kPOLLOUT = POLLOUT, kPOLLOUT = POLLOUT,
kPOLLERR = POLLERR, kPOLLERR = POLLERR,
kPOLLNVAL = POLLNVAL kPOLLNVAL = POLLNVAL
}; };
#endif #endif
@ -183,17 +185,39 @@ public:
//! Set socket to (non-)blocking operation //! Set socket to (non-)blocking operation
static int (PASCAL FAR *setblocking)(CNetwork::Socket s, bool blocking); static int (PASCAL FAR *setblocking)(CNetwork::Socket s, bool blocking);
#if WINDOWS_LIKE //! Turn Nagle algorithm on or off on socket
/*!
Set socket to send messages immediately (true) or to collect small
messages into one packet (false).
*/
static int (PASCAL FAR *setnodelay)(CNetwork::Socket s, bool nodelay);
private: private:
#if WINDOWS_LIKE
#define SELECT_TYPE_ARG1 int
#define SELECT_TYPE_ARG234 (fd_set *)
#define SELECT_TYPE_ARG5 (struct timeval *)
static void init2(HMODULE); static void init2(HMODULE);
static int PASCAL FAR poll2(PollEntry[], int nfds, int timeout);
static ssize_t PASCAL FAR read2(Socket s, void FAR * buf, size_t len); static ssize_t PASCAL FAR read2(Socket s, void FAR * buf, size_t len);
static ssize_t PASCAL FAR write2(Socket s, const void FAR * buf, size_t len); static ssize_t PASCAL FAR write2(Socket s, const void FAR * buf, size_t len);
static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking); static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking);
static int PASCAL FAR setnodelay2(CNetwork::Socket s, bool nodelay);
static int (PASCAL FAR *WSACleanup)(void); static int (PASCAL FAR *WSACleanup)(void);
static int (PASCAL FAR *__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *); static int (PASCAL FAR *__WSAFDIsSet)(CNetwork::Socket, fd_set FAR *);
static int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout); static int (PASCAL FAR *select)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
#endif #endif
#if UNIX_LIKE
static int PASCAL FAR gethostname2(char FAR * name, int namelen);
static int PASCAL FAR getsockerror2(void);
static int PASCAL FAR gethosterror2(void);
static int PASCAL FAR setblocking2(CNetwork::Socket s, bool blocking);
static int PASCAL FAR setnodelay2(CNetwork::Socket s, bool nodelay);
#endif
#if WINDOWS_LIKE || !HAVE_POLL
static int PASCAL FAR poll2(PollEntry[], int nfds, int timeout);
#endif
}; };
#endif #endif

View File

@ -208,8 +208,7 @@ CTCPSocket::init()
// turn off Nagle algorithm. we send lots of very short messages // turn off Nagle algorithm. we send lots of very short messages
// that should be sent without (much) delay. for example, the // that should be sent without (much) delay. for example, the
// mouse motion messages are much less useful if they're delayed. // mouse motion messages are much less useful if they're delayed.
CNetwork::TCPNoDelayType flag = 1; CNetwork::setnodelay(m_fd, true);
CNetwork::setsockopt(m_fd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag));
} }
void void

View File

@ -32,7 +32,22 @@
# include <X11/Xutil.h> # include <X11/Xutil.h>
#endif #endif
#if UNIX_LIKE #if UNIX_LIKE
#include <sys/poll.h> # if HAVE_POLL
# include <sys/poll.h>
# else
# if HAVE_SYS_SELECT_H
# include <sys/select.h>
# endif
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
# if HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# if HAVE_UNISTD_H
# include <unistd.h>
# endif
# endif
#endif #endif
// //
@ -240,19 +255,48 @@ CXWindowsScreen::mainLoop()
// use poll() to wait for a message from the X server or for timeout. // use poll() to wait for a message from the X server or for timeout.
// this is a good deal more efficient than polling and sleeping. // this is a good deal more efficient than polling and sleeping.
#if HAVE_POLL
struct pollfd pfds[1]; struct pollfd pfds[1];
pfds[0].fd = ConnectionNumber(m_display); pfds[0].fd = ConnectionNumber(m_display);
pfds[0].events = POLLIN; pfds[0].events = POLLIN;
#endif
while (!m_stop) { while (!m_stop) {
// compute timeout to next timer // compute timeout to next timer
#if HAVE_POLL
int timeout = (m_timers.empty() ? -1 : int timeout = (m_timers.empty() ? -1 :
static_cast<int>(1000.0 * m_timers.top())); static_cast<int>(1000.0 * m_timers.top()));
#else
struct timeval timeout;
struct timeval* timeoutPtr;
if (m_timers.empty()) {
timeoutPtr = NULL;
}
else {
timeout.tv_sec = static_cast<int>(m_timers.top());
timeout.tv_usec = static_cast<int>(1.0e+6 *
(m_timers.top() - timeout.tv_sec));
timeoutPtr = &timeout;
}
// initialize file descriptor sets
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(ConnectionNumber(m_display), &rfds);
#endif
// wait for message from X server or for timeout. also check // wait for message from X server or for timeout. also check
// if the thread has been cancelled. poll() should return -1 // if the thread has been cancelled. poll() should return -1
// with EINTR when the thread is cancelled. // with EINTR when the thread is cancelled.
m_mutex.unlock(); m_mutex.unlock();
#if HAVE_POLL
poll(pfds, 1, timeout); poll(pfds, 1, timeout);
#else
select(ConnectionNumber(m_display) + 1,
SELECT_TYPE_ARG234 &rfds,
SELECT_TYPE_ARG234 NULL,
SELECT_TYPE_ARG234 NULL,
SELECT_TYPE_ARG5 timeoutPtr);
#endif
CThread::testCancel(); CThread::testCancel();
m_mutex.lock(); m_mutex.lock();