天天看点

你真的懂select吗??

struct win_fd_set {

u_int fd_count;

1 
   volatile 
   double SIGFPE_REQ = 0.0f;

     2 

     3 
   struct idx_info {

     4     
   int read_pos_plus1;

     5     
   int write_pos_plus1;

     6 };

     7 

     8 
   struct win32op {

     9     unsigned num_fds_in_fd_sets;

    10     
   int resize_out_sets;

    11     
   struct win_fd_set *readset_in;

    12     
   struct win_fd_set *writeset_in;

    13     
   struct win_fd_set *readset_out;

    14     
   struct win_fd_set *writeset_out;

    15     
   struct win_fd_set *exset_out;

    16     unsigned signals_are_broken : 1;

    17 };

    18 

    19 
   static 
   void *win32_init(
   struct event_base *);

    20 
   static 
   int win32_add(
   struct event_base *, evutil_socket_t, 
   short old, 
   short events, 
   void *_idx);

    21 
   static 
   int win32_del(
   struct event_base *, evutil_socket_t, 
   short old, 
   short events, 
   void *_idx);

    22 
   static 
   int win32_dispatch(
   struct event_base *
   base, 
   struct timeval *);

    23 
   static 
   void win32_dealloc(
   struct event_base *);

    24 

    25 
   struct eventop win32ops = {

    26     "win32",

    27     win32_init,

    28     win32_add,

    29     win32_del,

    30     win32_dispatch,

    31     win32_dealloc,

    32     0, 
   /*
    doesn't need reinit 
   */

    33     0, 
   /*
    No features supported. 
   */

    34     
   sizeof(
   struct idx_info),

    35 };

    36 

    37 
   #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))

    38 

    39 
   static 
   int

    40 grow_fd_sets(
   struct win32op *op, unsigned new_num_fds)

    41 {

    42     size_t size;

    43 

    44     EVUTIL_ASSERT(new_num_fds >= op->readset_in->fd_count &&

    45            new_num_fds >= op->writeset_in->fd_count);

    46     EVUTIL_ASSERT(new_num_fds >= 1);

    47 

    48     size = FD_SET_ALLOC_SIZE(new_num_fds);

    49     
   if (!(op->readset_in = mm_realloc(op->readset_in, size)))

    50         
   return (-1);

    51     
   if (!(op->writeset_in = mm_realloc(op->writeset_in, size)))

    52         
   return (-1);

    53     op->resize_out_sets = 1;

    54     op->num_fds_in_fd_sets = new_num_fds;

    55     
   return (0);

    56 }

    57 

    58 
   static 
   int

    59 do_fd_set(
   struct win32op *op, 
   struct idx_info *ent, evutil_socket_t s, 
   int read)

    60 {

    61     
   struct win_fd_set *
   set = read ? op->readset_in : op->writeset_in;

    62     
   if (read) {

    63         
   if (ent->read_pos_plus1 > 0)

    64             
   return (0);

    65     } 
   else {

    66         
   if (ent->write_pos_plus1 > 0)

    67             
   return (0);

    68     }

    69     
   if (
   set->fd_count == op->num_fds_in_fd_sets) {

    70         
   if (grow_fd_sets(op, op->num_fds_in_fd_sets*2))

    71             
   return (-1);

    72         
   /*
    set pointer will have changed and needs reiniting! 
   */

    73         
   set = read ? op->readset_in : op->writeset_in;

    74     }

    75     
   set->fd_array[
   set->fd_count] = s;

    76     
   if (read)

    77         ent->read_pos_plus1 = 
   set->fd_count+1;

    78     
   else

    79         ent->write_pos_plus1 = 
   set->fd_count+1;

    80     
   return (
   set->fd_count++);

    81 }

    82 

    83 
   static 
   int

    84 do_fd_clear(
   struct event_base *
   base,

    85             
   struct win32op *op, 
   struct idx_info *ent, 
   int read)

    86 {

    87     
   int i;

    88     
   struct win_fd_set *
   set = read ? op->readset_in : op->writeset_in;

    89     
   if (read) {

    90         i = ent->read_pos_plus1 - 1;

    91         ent->read_pos_plus1 = 0;

    92     } 
   else {

    93         i = ent->write_pos_plus1 - 1;

    94         ent->write_pos_plus1 = 0;

    95     }

    96     
   if (i < 0)

    97         
   return (0);

    98     
   if (--
   set->fd_count != (unsigned)i) {

    99         
   struct idx_info *ent2;

   100         SOCKET s2;

   101         s2 = 
   set->fd_array[i] = 
   set->fd_array[
   set->fd_count];

   102 

   103         ent2 = evmap_io_get_fdinfo(&
   base->io, s2);

   104 

   105         
   if (!ent2) 
   /*
    This indicates a bug. 
   */

   106             
   return (0);

   107         
   if (read)

   108             ent2->read_pos_plus1 = i+1;

   109         
   else

   110             ent2->write_pos_plus1 = i+1;

   111     }

   112     
   return (0);

   113 }

   114 

   115 
   #define NEVENT 32

   116 
   void *

   117 win32_init(
   struct event_base *_base)

   118 {

   119     
   struct win32op *winop;

   120     size_t size;

   121     
   if (!(winop = mm_calloc(1, 
   sizeof(
   struct win32op))))

   122         
   return NULL;

   123     winop->num_fds_in_fd_sets = NEVENT;

   124     size = FD_SET_ALLOC_SIZE(NEVENT);

   125     
   if (!(winop->readset_in = mm_malloc(size)))

   126         
   goto err;

   127     
   if (!(winop->writeset_in = mm_malloc(size)))

   128         
   goto err;

   129     
   if (!(winop->readset_out = mm_malloc(size)))

   130         
   goto err;

   131     
   if (!(winop->writeset_out = mm_malloc(size)))

   132         
   goto err;

   133     
   if (!(winop->exset_out = mm_malloc(size)))

   134         
   goto err;

   135     winop->readset_in->fd_count = winop->writeset_in->fd_count = 0;

   136     winop->readset_out->fd_count = winop->writeset_out->fd_count

   137         = winop->exset_out->fd_count = 0;

   138 

   139     
   if (evsig_init(_base) < 0)

   140         winop->signals_are_broken = 1;

   141 

   142     
   return (winop);

   143  err:

   144     XFREE(winop->readset_in);

   145     XFREE(winop->writeset_in);

   146     XFREE(winop->readset_out);

   147     XFREE(winop->writeset_out);

   148     XFREE(winop->exset_out);

   149     XFREE(winop);

   150     
   return (NULL);

   151 }

   152 

   153 
   int

   154 win32_add(
   struct event_base *
   base, evutil_socket_t fd,

   155              
   short old, 
   short events, 
   void *_idx)

   156 {

   157     
   struct win32op *win32op = 
   base->evbase;

   158     
   struct idx_info *idx = _idx;

   159 

   160     
   if ((events & EV_SIGNAL) && win32op->signals_are_broken)

   161         
   return (-1);

   162 

   163     
   if (!(events & (EV_READ|EV_WRITE)))

   164         
   return (0);

   165 

   166     event_debug(("%s: adding event for %d", __func__, (
   int)fd));

   167     
   if (events & EV_READ) {

   168         
   if (do_fd_set(win32op, idx, fd, 1)<0)

   169             
   return (-1);

   170     }

   171     
   if (events & EV_WRITE) {

   172         
   if (do_fd_set(win32op, idx, fd, 0)<0)

   173             
   return (-1);

   174     }

   175     
   return (0);

   176 }

   177 

   178 
   int

   179 win32_del(
   struct event_base *
   base, evutil_socket_t fd, 
   short old, 
   short events,

   180           
   void *_idx)

   181 {

   182     
   struct win32op *win32op = 
   base->evbase;

   183     
   struct idx_info *idx = _idx;

   184 

   185     event_debug(("%s: Removing event for "EV_SOCK_FMT,

   186         __func__, EV_SOCK_ARG(fd)));

   187     
   if (events & EV_READ)

   188         do_fd_clear(
   base, win32op, idx, 1);

   189     
   if (events & EV_WRITE)

   190         do_fd_clear(
   base, win32op, idx, 0);

   191 

   192     
   return 0;

   193 }

   194 

   195 
   static 
   void

   196 fd_set_copy(
   struct win_fd_set *
   out, 
   const 
   struct win_fd_set *
   in)

   197 {

   198     
   out->fd_count = 
   in->fd_count;

   199     memcpy(
   out->fd_array, 
   in->fd_array, 
   in->fd_count * (
   sizeof(SOCKET)));

   200 }

   201 

   202 
   /*
   

   203 
     static void dump_fd_set(struct win_fd_set *s)

   204 
     {

   205 
     unsigned int i;

   206 
     printf("[ ");

   207 
     for(i=0;i<s->fd_count;++i)

   208 
     printf("%d ",(int)s->fd_array[i]);

   209 
     printf("]\n");

   210 
     }

   211 
   
   */

   212 

   213 
   int

   214 win32_dispatch(
   struct event_base *
   base, 
   struct timeval *tv)

   215 {

   216     
   struct win32op *win32op = 
   base->evbase;

   217     
   int res = 0;

   218     unsigned j, i;

   219     
   int fd_count;

   220     SOCKET s;

   221 

   222     
   if (win32op->resize_out_sets) {

   223         size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets);

   224         
   if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size)))

   225             
   return (-1);

   226         
   if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size)))

   227             
   return (-1);

   228         
   if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size)))

   229             
   return (-1);

   230         win32op->resize_out_sets = 0;

   231     }

   232 

   233     fd_set_copy(win32op->readset_out, win32op->readset_in);

   234     fd_set_copy(win32op->exset_out, win32op->writeset_in);

   235     fd_set_copy(win32op->writeset_out, win32op->writeset_in);

   236 

   237     fd_count =

   238         (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ?

   239         win32op->readset_out->fd_count : win32op->writeset_out->fd_count;

   240 

   241     
   if (!fd_count) {

   242         
   long msec = tv ? evutil_tv_to_msec(tv) : LONG_MAX;

   243         
   /*
    Sleep's DWORD argument is unsigned long 
   */

   244         
   if (msec < 0)

   245             msec = LONG_MAX;

   246         
   /*
    Windows doesn't like you to call select() with no sockets 
   */

   247         Sleep(msec);

   248         
   return (0);

   249     }

   250 

   251     EVBASE_RELEASE_LOCK(
   base, th_base_lock);

   252 

   253     res = select(fd_count,

   254              (
   struct fd_set*)win32op->readset_out,

   255              (
   struct fd_set*)win32op->writeset_out,

   256              (
   struct fd_set*)win32op->exset_out, tv);

   257 

   258     EVBASE_ACQUIRE_LOCK(
   base, th_base_lock);

   259 

   260     event_debug(("%s: select returned %d", __func__, res));

   261 

   262     
   if (res <= 0) {

   263         
   return res;

   264     }

   265 

   266     
   if (win32op->readset_out->fd_count) {

   267         i = rand() % win32op->readset_out->fd_count;

   268         
   for (j=0; j<win32op->readset_out->fd_count; ++j) {

   269             
   if (++i >= win32op->readset_out->fd_count)

   270                 i = 0;

   271             s = win32op->readset_out->fd_array[i];

   272             evmap_io_active(
   base, s, EV_READ);

   273         }

   274     }

   275     
   if (win32op->exset_out->fd_count) {

   276         i = rand() % win32op->exset_out->fd_count;

   277         
   for (j=0; j<win32op->exset_out->fd_count; ++j) {

   278             
   if (++i >= win32op->exset_out->fd_count)

   279                 i = 0;

   280             s = win32op->exset_out->fd_array[i];

   281             evmap_io_active(
   base, s, EV_WRITE);

   282         }

   283     }

   284     
   if (win32op->writeset_out->fd_count) {

   285         SOCKET s;

   286         i = rand() % win32op->writeset_out->fd_count;

   287         
   for (j=0; j<win32op->writeset_out->fd_count; ++j) {

   288             
   if (++i >= win32op->writeset_out->fd_count)

   289                 i = 0;

   290             s = win32op->writeset_out->fd_array[i];

   291             evmap_io_active(
   base, s, EV_WRITE);

   292         }

   293     }

   294     
   return (0);

   295 }

   296 

   297 
   void

   298 win32_dealloc(
   struct event_base *_base)

   299 {

   300     
   struct win32op *win32op = _base->evbase;

   301 

   302     evsig_dealloc(_base);

   303     
   if (win32op->readset_in)

   304         mm_free(win32op->readset_in);

   305     
   if (win32op->writeset_in)

   306         mm_free(win32op->writeset_in);

   307     
   if (win32op->readset_out)

   308         mm_free(win32op->readset_out);

   309     
   if (win32op->writeset_out)

   310         mm_free(win32op->writeset_out);

   311     
   if (win32op->exset_out)

   312         mm_free(win32op->exset_out);

   313     
   /*
    XXXXX free the tree. 
   */

   314 

   315     memset(win32op, 0, 
   sizeof(win32op));

   316     mm_free(win32op);

   317      

继续阅读