typedef struct fd_set {u_int fd_count; /* how many are SET? */SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */// FD_SETSIZE: 最大连接数据 } fd_set;
2, 添加文件描述符到 fd_set中的数组中fd_array
#define FD_SET(fd, set) do { \u_int __i; \for (__i &#61; 0; __i <((fd_set FAR *)(set))->fd_count; __i&#43;&#43;) { \ // 查找fd_array数组中文件描述符的位置if (((fd_set FAR *)(set))->fd_array[__i] &#61;&#61; (fd)) { \break; \} \} \if (__i &#61;&#61; ((fd_set FAR *)(set))->fd_count) { \if (((fd_set FAR *)(set))->fd_count fd_array[__i] &#61; (fd); \((fd_set FAR *)(set))->fd_count&#43;&#43;; \} \} \ } while(0, 0)
3, 在数组中删除文件描述符
#define FD_CLR(fd, set) do { \u_int __i; \for (__i &#61; 0; __i <((fd_set FAR *)(set))->fd_count ; __i&#43;&#43;) { \if (((fd_set FAR *)(set))->fd_array[__i] &#61;&#61; fd) { \while (__i <((fd_set FAR *)(set))->fd_count-1) { \((fd_set FAR *)(set))->fd_array[__i] &#61; \((fd_set FAR *)(set))->fd_array[__i&#43;1]; \__i&#43;&#43;; \} \((fd_set FAR *)(set))->fd_count--; \break; \} \} \ } while(0, 0)
extern int PASCAL FAR __WSAFDIsSet(SOCKET fd, fd_set FAR *);#define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count&#61;0)#define FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set FAR *)(set))
void select_reactor::run(bool block, op_queue& ops) {boost::asio::detail::mutex::scoped_lock lock(mutex_);#if defined(BOOST_ASIO_HAS_IOCP)// Check if the thread is supposed to stop.if (stop_thread_)return; #endif // defined(BOOST_ASIO_HAS_IOCP)// Set up the descriptor sets.for (int i &#61; 0; i max_fd)max_fd &#61; fd_sets_[i].max_descriptor();}#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)// Connection operations on Windows use both except and write fd_sets.have_work_to_do &#61; have_work_to_do || !op_queue_[connect_op].empty();fd_sets_[write_op].set(op_queue_[connect_op], ops);if (fd_sets_[write_op].max_descriptor() > max_fd)max_fd &#61; fd_sets_[write_op].max_descriptor();fd_sets_[except_op].set(op_queue_[connect_op], ops);if (fd_sets_[except_op].max_descriptor() > max_fd)max_fd &#61; fd_sets_[except_op].max_descriptor(); #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)// We can return immediately if there&#39;s no work to do and the reactor is// not supposed to block.if (!block && !have_work_to_do)return;// Determine how long to block while waiting for events.timeval tv_buf &#61; { 0, 0 };timeval* tv &#61; block ? get_timeout(tv_buf) : &tv_buf;lock.unlock();// Block on the select call until descriptors become ready.boost::system::error_code ec;int retval &#61; socket_ops::select(static_cast(max_fd &#43; 1),fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec);// Reset the interrupter.if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor())){interrupter_.reset();--retval;}lock.lock();// Dispatch all ready operations.if (retval > 0){ #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)// Connection operations on Windows use both except and write fd_sets.fd_sets_[except_op].perform(op_queue_[connect_op], ops);fd_sets_[write_op].perform(op_queue_[connect_op], ops); #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)// Exception operations must be processed first to ensure that any// out-of-band data is read before normal data.for (int i &#61; max_select_ops - 1; i >&#61; 0; --i)fd_sets_[i].perform(op_queue_[i], ops);}timer_queues_.get_ready_timers(ops); }