1. 程式人生 > >你真的懂select嗎??

你真的懂select嗎??

  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 *basestruct 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 *outconst 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 *basestruct 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 }