#ifndef IO_FILE_DESCRIPTOR_SET_H #define IO_FILE_DESCRIPTOR_SET_H #ifndef _WIN32 #include #else #include #endif namespace io { #ifdef _WIN32 typedef SOCKET file_descriptor_type; #else typedef int file_descriptor_type; #endif class file_descriptor_set : boost::noncopyable { public: typedef file_descriptor_type value_type; file_descriptor_set() #ifndef _WIN32 : max_( 0 ) #endif { FD_ZERO( &fd_set_ ); } void insert( value_type fd ) { #ifndef _WIN32 max_ = std::max( max_, fd ); #endif FD_SET( fd, &fd_set_ ); } void erase( value_type fd ) { FD_CLR( fd, &fd_set_ ); #ifndef _WIN32 if( fd == max_ ) { --max_; recalc_max(); } #endif } bool count( value_type fd ) { return (FD_ISSET( fd, &fd_set_ ) != 0) ? 1 : 0; } private: fd_set fd_set_; friend int select( file_descriptor_set & read_set, file_descriptor_set & write_set, file_descriptor_set & except_set, timeval *timeout = 0 ) { int max_max = std::max( read_set.max(), std::max( write_set.max(), except_set.max() ) ); int ret = ::select( max_max + 1, &read_set.fd_set_, &write_set.fd_set_, &except_set.fd_set_, timeout ); read_set.recalc_max(); write_set.recalc_max(); except_set.recalc_max(); return ret; } friend int select( file_descriptor_set & read_set, file_descriptor_set & write_set, timeval *timeout = 0 ) { int max_max = std::max( read_set.max(), write_set.max() ); int ret = ::select( max_max + 1, &read_set.fd_set_, &write_set.fd_set_, 0, timeout ); read_set.recalc_max(); write_set.recalc_max(); return ret; } void recalc_max() { #ifndef _WIN32 while( max_ != 0 && count( max_ ) == 0 ) { --max_; } #endif } #ifndef _WIN32 value_type max_; int max() const { return max_; } #else int max() const { return 0; } #endif }; } #endif