/* * 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 usec ) { for( ;; ) { struct timeval tv; if( read ) SetRead(); else ClearRead(); if( write ) SetWrite(); else ClearWrite(); tv.tv_sec = 0; tv.tv_usec = usec; switch( select( fd+1, Rfds(), Wfds(), 0, usec >= 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 | 18760 | rlranft |
Populate -o //guest/perforce_software/p4/... //guest/rlranft/p4/.... |
||
//guest/perforce_software/p4/2015-1/net/netselect.h | |||||
#1 | 15903 | Matt Attaway | Everything should be happy now between the Workshop and the depot paths | ||
//guest/perforce_software/p4/2015_1/net/netselect.h | |||||
#1 | 15901 | Matt Attaway | Clean up code to fit modern Workshop naming standards | ||
//guest/perforce_software/p4/2015.1/net/netselect.h | |||||
#1 | 12190 | Matt Attaway | Initial drop of 2015.1 p4/p4api source |