/*
* Copyright 2009 Perforce Software. All rights reserved.
*
* This file is part of Perforce - the FAST SCM System.
*/
/*
* NetTcpSelector -- isolation of select() call for TCP
*
* Public methods:
*
* NetTcpSelector( int t ) - create a selector for file descriptor t
*
* NetTcpSelector::Select( int &read, int &write, int usec, Error *e )
*
* Blocks waiting for read (if read set) and/or write
* (if write set). Sets read if data ready to read, write
* if data ready to write.
*
* Waits at most usec microseconds, or forever if usec < 0.
*
* Returns 0 if timeout.
* Returns -1 on error (with Error set).
* Returns >0 on data ready.
*
* NetTcpSelector::Peek()
*
* Returns 1 if data is available to read, 0 if not (EOF).
* Call Select() first.
*/
# if defined( AF_UNIX ) || defined( OS_NT )
# if !defined( OS_UNIXWARE7 ) && !defined( OS_SINIX ) && !defined( OS_OS2 )
// Add HPUX11 to standard select using fd_set, anything greater than 256
// causes select() to sleep.
# if defined( OS_HPUX11 ) || defined( OS_NT )
# define USE_SELECT_FDSET
# else
# define USE_SELECT_BITARRAY
# endif
# define USE_SELECTOR
# endif
# endif
class NetTcpSelector
{
public:
# ifdef USE_SELECT_BITARRAY
// Choose the max of ( fd + 1 ) and FD_SETSIZE in case the
// select call always expects at least FD_SETSIZE large...
// This is a safety measure mostly, but I have observed that
// the FreeBSD select man page says it always looks at 256
// descriptors so I'm erring on the conservative side..
NetTcpSelector( int t )
{
fd = t;
if( ++t < FD_SETSIZE )
t = FD_SETSIZE;
rfd = new BitArray( t );
wfd = new BitArray( t );
}
~NetTcpSelector()
{
delete rfd;
delete wfd;
}
void SetRead() { rfd->tas( fd ); }
void ClearRead() { rfd->clear( fd ); }
int CheckRead() { return (*rfd)[ fd ]; }
fd_set *Rfds() { return (fd_set*)rfd->fdset(); }
void SetWrite() { wfd->tas( fd ); }
void ClearWrite() { wfd->clear( fd ); }
int CheckWrite() { return (*wfd)[ fd ]; }
fd_set *Wfds() { return (fd_set*)wfd->fdset(); }
BitArray *rfd;
BitArray *wfd;
# endif
# ifdef USE_SELECT_FDSET
NetTcpSelector( int t )
{
fd = t;
FD_ZERO( &rfd );
FD_ZERO( &wfd );
}
void SetRead() { FD_SET( fd, &rfd ); }
void ClearRead() { FD_CLR( fd, &rfd ); }
int CheckRead() { return FD_ISSET( fd, &rfd ); }
fd_set *Rfds() { return &rfd; }
void SetWrite() { FD_SET( fd, &wfd ); }
void ClearWrite() { FD_CLR( fd, &wfd ); }
int CheckWrite() { return FD_ISSET( fd, &wfd ); }
fd_set *Wfds() { return &wfd; }
fd_set rfd;
fd_set wfd;
# endif
# ifdef USE_SELECTOR
/* Select() that works with BitArray or fd_set */
int Select( int &read, int &write, int msec )
{
for( ;; )
{
struct timeval tv;
if( read ) SetRead(); else ClearRead();
if( write ) SetWrite(); else ClearWrite();
if( msec < 1000 )
{
tv.tv_sec = 0;
tv.tv_usec = msec * 1000;
}
else
{
tv.tv_sec = msec / 1000;
tv.tv_usec = ( msec % 1000 ) * 1000;
}
switch( select( fd+1, Rfds(), Wfds(), 0, msec >= 0 ? &tv : 0 ) )
{
case -1:
if( errno == EINTR )
continue;
return -1;
case 0:
// duh linux leaves fd_sets set on timeout
read = write = 0;
return 0;
default:
read = CheckRead();
write = CheckWrite();
return 1;
}
}
}
# if defined(OS_NT) || defined(OS_SOLARIS)
int Peek()
{
char buf[2];
return recv( fd, buf, 1, MSG_PEEK ) > 0;
}
# else
int Peek()
{
int nread;
return ioctl( fd, FIONREAD, &nread ) >= 0 && nread > 0;
}
# endif
int fd;
# else
/* Braindead version: ignorance is bliss */
NetTcpSelector( int ) {}
int Select( int &read, int &write, int time )
{
read = write = 1;
return 1;
}
int Peek()
{
return 1;
}
# endif
} ;
# |
Change |
User |
Description |
Committed |
|
#1
|
22562 |
rlranft |
Populate -o //guest/perforce_software/p4/2017-1/...
//guest/rlranft/p4/2017-1/.... |
|
|
//guest/perforce_software/p4/2017-1/net/netselect.h |
#1
|
22288 |
mark_mears |
import 2017.1 code drop |
|
|