讓Libevent 在window下 支持 IOCP

Libevent 的強大就不說了,但因爲在window下使用的是 select 機制 ,除了效率低下意外還有一個討厭的"FD_SETSIZE"限制,因此一直 但願能支持IOCP,但是如今已經到2.0仍是沒可以支持。css


無心中在網上發現了個支持IOCP的libevent版本,是1.4.7版的。不過不要緊,把其中的一個關鍵文件"win32iocp.c"拷貝到最新的1.4.14b版本中,並在"event.c" 中修改:html

.....
#ifdef HAVE_POLL
extern const struct eventop pollops;
#endif
#ifdef HAVE_EPOLL
extern const struct eventop epollops;
#endif
#ifdef HAVE_WORKING_KQUEUE
extern const struct eventop kqops;
#endif
#ifdef HAVE_DEVPOLL
extern const struct eventop devpollops;
#endif
#ifdef WIN32
#ifndef _EVENT_NOIOCP
extern const struct eventop win32iocpops;
#endif
extern const struct eventop win32ops;
#endifnode

.....windows

static const struct eventop *eventops[] = {
#ifdef HAVE_EVENT_PORTS
&evportops,
#endif
#ifdef HAVE_WORKING_KQUEUE
&kqops,
#endif
#ifdef HAVE_EPOLL
&epollops,
#endif
#ifdef HAVE_DEVPOLL
&devpollops,
#endif
#ifdef HAVE_POLL
&pollops,
#endif
#ifdef HAVE_SELECT
&selectops,
#endif
#ifdef WIN32app

#ifndef _EVENT_NOIOCP
&win32iocpops,
#endif
socket

&win32ops,
#endif
NULL
};ide

....oop


紅色部分是添加的。this

這樣就能夠很好的支持IOCP了。spa


附: win32iocp.c 代碼

 1:   /*
 2:  * win32iocp.c
 3:  *
 4:  * Integerate Windows I/O Completion Port into Libevent.
 5:  *
 6:  * Submitted by Stephen Liu <stephen.nil@gmail.com>
 7:  *
 8:  * Redistribution and use in source and binary forms, with or without
 9:  * modification, are permitted provided that the following conditions
 10:  * are met:
 11:  * 1. Redistributions of source code must retain the above copyright
 12:  * notice, this list of conditions and the following disclaimer.
 13:  * 2. Redistributions in binary form must reproduce the above copyright
 14:  * notice, this list of conditions and the following disclaimer in the
 15:  * documentation and/or other materials provided with the distribution.
 16:  * 3. The name of the author may not be used to endorse or promote products
 17:  * derived from this software without specific prior written permission.
 18:  *
 19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 28:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29:  */
 30:   #ifdef _MSC_VER
 31:   #include "./config.h"
 32:   #else
 33:   /* Avoid the windows/msvc thing. */
 34:   #include "../config.h"
 35:   #endif
 36:   #ifndef _EVENT_NOIOCP
 37:   #include <winsock2.h>
 38:   #include <mswsock.h>
 39:   #include <windows.h>
 40:   #include <sys/types.h>
 41:   #include <sys/queue.h>
 42:   #include <signal.h>
 43:   #include <stdio.h>
 44:   #include <stdlib.h>
 45:   #include <string.h>
 46:   #include <errno.h>
 47:   #include <assert.h>
 48:   #include "event.h"
 49:   #include "event-internal.h"
 50:   #include "evsignal.h"
 51:   #include "log.h"
 52:   #include "tree.h"
 53:   struct win32iocp_event {
 54:       OVERLAPPED overlapped;
 55:       struct event * ev;
 56:       short event;
 57:       struct win32iocp_event * next;
 58:   };
 59:   struct win32iocp_entry {
 60:       RB_ENTRY(win32iocp_entry) node;
 61:       SOCKET sock;
 62:       char nread, nwrite;
 63:   };
 64:   static int
 65:   compare(struct win32iocp_entry *a, struct win32iocp_entry *b)
 66:   {
 67:       if (a->sock < b->sock)
 68:           return -1;
 69:       else if (a->sock > b->sock)
 70:           return 1;
 71:       else
 72:           return 0;
 73:   }
 74:   struct win32iocp_op {
 75:       struct win32iocp_event * freelist;
 76:       int nfreecount;
 77:       HANDLE iocp;
 78:       /* objects[0] for iocp operations, object[1..63] for WSAEventSelect operations */
 79:       HANDLE objects[MAXIMUM_WAIT_OBJECTS];
 80:       struct event * events[MAXIMUM_WAIT_OBJECTS];
 81:       /* keep persist events between two win32iocp_dispatch call */
 82:       struct win32iocp_event * persist;
 83:       int npersist;
 84:       RB_HEAD(win32iocp_map, win32iocp_entry) event_root;
 85:   };
 86:   RB_PROTOTYPE(win32iocp_map, win32iocp_entry, node, compare);
 87:   RB_GENERATE(win32iocp_map, win32iocp_entry, node, compare);
 88:   static void *win32iocp_init    (struct event_base *);
 89:   static int win32iocp_add    (void *, struct event *);
 90:   static int win32iocp_del    (void *, struct event *);
 91:   static int win32iocp_dispatch    (struct event_base *, void *, struct timeval *);
 92:   static void win32iocp_dealloc    (struct event_base *, void *);
 93:   static struct win32iocp_event * win32iocp_event_new (struct win32iocp_op *);
 94:   static void win32iocp_event_free (struct win32iocp_op *, struct win32iocp_event *);
 95:   static int win32iocp_eventselects_add (struct win32iocp_op *, struct event *);
 96:   static int win32iocp_eventselects_del (struct win32iocp_op *, struct event *);
 97:   static int win32iocp_event_loop (struct win32iocp_op *);
 98:   static int win32iocp_event_active (struct win32iocp_op * win32iocp_op,
 99:           int fd, struct win32iocp_event * event);
 100:   static void win32iocp_persist_add (struct win32iocp_op *, struct win32iocp_event *);
 101:   static int win32iocp_persist_del (struct win32iocp_op *, int, short);
 102:   static int win32iocp_persist_dispatch (struct win32iocp_op *);
 103:   struct eventop win32iocpops = {
 104:       "win32iocp",
 105:       win32iocp_init,
 106:       win32iocp_add,
 107:       win32iocp_del,
 108:       win32iocp_dispatch,
 109:       win32iocp_dealloc,
 110:       1 /* need reinit */
 111:   };
 112:   static const char *
 113:   win32iocp_strerror( DWORD lastError, char * errmsg, size_t len )
 114:   {
 115:       if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, lastError, 0,
 116:               errmsg, len - 1, NULL)) {
 117:           /* if we fail, call ourself to find out why and return that error */
 118:           return win32iocp_strerror( GetLastError(), errmsg, len );
 119:       }
 120:       return errmsg;
 121:   }
 122:   static struct win32iocp_entry *
 123:   win32iocp_get_entry(struct win32iocp_op *op, SOCKET s, int create)
 124:   {
 125:       struct win32iocp_entry key, *val;
 126:       key.sock = s;
 127:       val = RB_FIND(win32iocp_map, &op->event_root, &key);
 128:       if (val || !create)
 129:           return val;
 130:       if (!(val = calloc(1, sizeof(struct win32iocp_entry)))) {
 131:           event_warn("win32iocp_get_entry: out of memory");
 132:           return NULL;
 133:       }
 134:       val->sock = s;
 135:       RB_INSERT(win32iocp_map, &op->event_root, val);
 136:       return val;
 137:   }
 138:   static struct win32iocp_event *
 139:   win32iocp_event_new (struct win32iocp_op * op)
 140:   {
 141:       struct win32iocp_event * event = NULL;
 142:       if (NULL != op->freelist) {
 143:           event = op->freelist;
 144:           op->freelist = event->next;
 145:           event->next = NULL;
 146:           -- op->nfreecount;
 147:       } else {
 148:           event =  calloc( 1, sizeof (struct win32iocp_event) );
 149:       }
 150:       return event;
 151:   }
 152:   static void
 153:   win32iocp_event_free (struct win32iocp_op * op, struct win32iocp_event * event)
 154:   {
 155:       if (op->nfreecount < 512) {
 156:           memset (event, 0, sizeof (struct win32iocp_event) );
 157:           event->next = op->freelist;
 158:           op->freelist = event;
 159:           ++ op->nfreecount;
 160:       } else {
 161:           free( event );
 162:       }
 163:   }
 164:   int
 165:   win32iocp_eventselect_add (struct win32iocp_op * op, struct event * event, int type)
 166:   {
 167:       int i = 0, index = -1, avail = -1;
 168:       for (i = 1; i < MAXIMUM_WAIT_OBJECTS && index < 0; i++) {
 169:           struct event * iter = op->events[i];
 170:           if (iter == event) index = i;
 171:           if (NULL != iter && iter->ev_fd == event->ev_fd) index = i;
 172:           if (NULL == iter && avail < 0) avail = i;
 173:       }
 174:       if (index > 0) {
 175:           op->events[index] = event;
 176:       } else {
 177:           if (avail > 0) {
 178:               op->events[avail] = event;
 179:               index = avail;
 180:           }
 181:       }
 182:       if (index > 0 ) {
 183:           if (SOCK_STREAM == type) {
 184:               if (event->ev_events & EV_CONNECT) {
 185:                   WSAEventSelect( event->ev_fd, op->objects[index], FD_CONNECT );
 186:               } else {
 187:                   WSAEventSelect( event->ev_fd, op->objects[index], FD_ACCEPT );
 188:               }
 189:           } else {
 190:               if (event->ev_events & EV_READ) {
 191:                   WSAEventSelect( event->ev_fd, op->objects[index], FD_READ );
 192:               } else {
 193:                   assert (event->ev_events & EV_WRITE);
 194:                   WSAEventSelect( event->ev_fd, op->objects[index], FD_WRITE );
 195:               }
 196:           }
 197:       }
 198:       return (index < 0) ? -1 : 0;
 199:   }
 200:   int
 201:   win32iocp_eventselect_del (struct win32iocp_op * op, struct event * event)
 202:   {
 203:       int i = 0, index = -1;
 204:       for (i = 1; i < MAXIMUM_WAIT_OBJECTS && index < 0; i++) {
 205:           struct event * iter = op->events[i];
 206:           if (iter == event) index = i;
 207:           if (NULL != iter && iter->ev_fd == event->ev_fd) index = i;
 208:       }
 209:       if (index > 0) {
 210:           WSAEventSelect( event->ev_fd, op->objects[index], 0 );
 211:           op->events[index] = NULL;
 212:       }
 213:       return index > 0 ? -1 : 0;
 214:   }
 215:   void
 216:   win32iocp_persist_add (struct win32iocp_op * op, struct win32iocp_event * event)
 217:   {
 218:       event->next = op->persist;
 219:       op->persist = event;
 220:       op->npersist++;
 221:   }
 222:   int
 223:   win32iocp_persist_del (struct win32iocp_op * op, int fd, short event)
 224:   {
 225:       struct win32iocp_event ** curr = &( op->persist );
 226:       for ( ; *curr; curr = &((*curr)->next) ) {
 227:           if ((*curr)->ev->ev_fd == fd && (*curr)->event == event ) {
 228:               struct win32iocp_event * todel = *curr;
 229:               *curr = todel->next;
 230:               win32iocp_event_free( op, todel );
 231:               op->npersist--;
 232:               return 0;
 233:           }
 234:       }
 235:       return -1;
 236:   }
 237:   /* 0 : OK, -1 : has error and the error events have been actived */
 238:   int
 239:   win32iocp_persist_dispatch (struct win32iocp_op * op)
 240:   {
 241:   #define WIN32_IS_RETRY(lastError) /
 242:       (ERROR_INVALID_USER_BUFFER == lastError /
 243:           || ERROR_NOT_ENOUGH_QUOTA == lastError /
 244:           || ERROR_NOT_ENOUGH_MEMORY == lastError)
 245:       int ret = 0, fd = -1;
 246:       struct win32iocp_entry * entry = NULL;
 247:       struct win32iocp_event * curr = NULL, * errorlist = NULL, * retrylist = NULL;
 248:       int lastError = 0;
 249:       for ( ; op->persist; ) {
 250:           curr = op->persist;
 251:           op->persist = curr->next;
 252:           --op->npersist;
 253:           fd = curr->ev->ev_fd;
 254:           entry = win32iocp_get_entry (op, fd, 0);
 255:           if (NULL == entry) {
 256:               event_warn("win32iocp_persist_dispatch: cannot found fd(%d), dangerous", fd);
 257:               curr->next = errorlist;
 258:               errorlist = curr;
 259:               continue;
 260:           }
 261:           if (EV_READ == curr->event) {
 262:               DWORD recvBytes = 0;
 263:               memset( &( curr->overlapped ), 0, sizeof( OVERLAPPED ) );
 264:               curr->overlapped.hEvent = op->objects[0];
 265:               if( FALSE == ReadFile( (HANDLE)fd, NULL, 0, &recvBytes, &( curr->overlapped ) ) ) {
 266:                   lastError = WSAGetLastError();
 267:                   if( ERROR_IO_PENDING != lastError ) {
 268:                       event_warn("win32iocp_persist_dispatch: ReadFile failed, errno %d", lastError);
 269:                       if (WIN32_IS_RETRY(lastError)) {
 270:                           /* recoverable error, left it for next loop */
 271:                           curr->next = retrylist;
 272:                           retrylist = curr;
 273:                       } else {
 274:                           curr->next = errorlist;
 275:                           errorlist = curr;
 276:                       }
 277:                       continue;
 278:                   }
 279:               }
 280:               entry->nread = 1;
 281:           }
 282:           if (EV_WRITE == curr->event) {
 283:               DWORD sendBytes = 0;
 284:               memset( &( curr->overlapped ), 0, sizeof( OVERLAPPED ) );
 285:               curr->overlapped.hEvent = op->objects[0];
 286:               if( FALSE == WriteFile( (HANDLE)fd, NULL, 0, &sendBytes, &( curr->overlapped ) ) ) {
 287:                   lastError = WSAGetLastError();
 288:                   if( ERROR_IO_PENDING != lastError ) {
 289:                       event_warn("win32iocp_persist_dispatch: WriteFile failed, errno %d", lastError);
 290:                       if (WIN32_IS_RETRY(lastError)) {
 291:                           /* recoverable error, left it for next loop */
 292:                           curr->next = retrylist;
 293:                           retrylist = curr;
 294:                       } else {
 295:                           curr->next = errorlist;
 296:                           errorlist = curr;
 297:                       }
 298:                       continue;
 299:                   }
 300:               }
 301:               entry->nwrite = 1;
 302:           }
 303:       }
 304:       op->persist = retrylist;
 305:       op->npersist = 0;
 306:       for( curr = op->persist; curr; curr = curr->next)
 307:           ++op->npersist;
 308:       for( curr = errorlist; curr; ) {
 309:           event_debug (("win32iocp_persist_dispatch: active error event, fd %d, ev %p, event %d",
 310:                   curr->ev->ev_fd, curr->ev, curr->event));
 311:           errorlist = curr->next;
 312:           event_active (curr->ev, curr->event, 1);
 313:           win32iocp_event_free (op, curr);
 314:           curr = errorlist;
 315:           ret = -1;
 316:       }
 317:       return ret;
 318:   }
 319:   static void *
 320:   win32iocp_init(struct event_base *base)
 321:   {
 322:       HANDLE iocp;
 323:       int i = 0;
 324:       struct win32iocp_op * win32iocp_op;
 325:       /* Disable win32 iocp when this environment variable is set */
 326:       if (getenv("EVENT_NOWIN32IOCP"))
 327:           return (NULL);
 328:       /* Initalize the kernel queue */
 329:       iocp = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );
 330:       if (NULL == iocp) {
 331:           event_warn("CreateIoCompletionPort");
 332:           return (NULL);
 333:       }
 334:       if (!(win32iocp_op = calloc(1, sizeof(struct win32iocp_op)))) {
 335:           event_warn("calloc");
 336:           CloseHandle( iocp );
 337:           return( NULL );
 338:       }
 339:       win32iocp_op->iocp = iocp;
 340:       /* Initalize fields */
 341:       RB_INIT(&win32iocp_op->event_root);
 342:       for (i = 0; i < MAXIMUM_WAIT_OBJECTS; i++ ) {
 343:           win32iocp_op->objects[i] = CreateEvent( NULL, FALSE, FALSE, NULL );
 344:       }
 345:       evsignal_init(base);
 346:       return (win32iocp_op);
 347:   }
 348:   /* 0 : not active event, 1 : has active event */
 349:   static int
 350:   win32iocp_event_active (struct win32iocp_op * win32iocp_op,
 351:           int fd, struct win32iocp_event * event)
 352:   {
 353:       int count = 0;
 354:       struct win32iocp_entry * entry = NULL;
 355:       entry = win32iocp_get_entry (win32iocp_op, fd, 0);
 356:       if (NULL == entry) {
 357:           event_warn("win32iocp_event_active: cannot found fd(%d), dangerous", fd);
 358:           win32iocp_event_free (win32iocp_op, event);
 359:           return (count);
 360:       }
 361:       if (EV_READ == event->event && entry->nread) {
 362:           ++count;
 363:           event_active (event->ev, EV_READ, 1);
 364:           if (EV_PERSIST & event->ev->ev_events) {
 365:               win32iocp_persist_add (win32iocp_op, event);
 366:           } else {
 367:               entry->nread = 0;
 368:           }
 369:       }
 370:       if (EV_WRITE == event->event && entry->nwrite) {
 371:           ++count;
 372:           event_active (event->ev, EV_WRITE, 1);
 373:           if (EV_PERSIST & event->ev->ev_events) {
 374:               win32iocp_persist_add (win32iocp_op, event);
 375:           } else {
 376:               entry->nwrite = 0;
 377:           }
 378:       }
 379:       /* this event has been canceled by calling event_del */
 380:       if (0 == count) {
 381:           event_debug (("win32iocp_event_active: ignore pending operation, fd %d, ev %p, event %d",
 382:                   fd, event->ev, event->event));
 383:       }
 384:       if (0 == count || (! (EV_PERSIST & event->ev->ev_events) ))
 385:           win32iocp_event_free (win32iocp_op, event);
 386:       return count;
 387:   }
 388:   /* -1 : Fail, >= 0 : count of event */
 389:   static int
 390:   win32iocp_event_loop(struct win32iocp_op * win32iocp_op)
 391:   {
 392:       int count = 0;
 393:       for ( ; ; ) {
 394:           BOOL isSuccess = FALSE;
 395:           DWORD bytesTransferred = 0;
 396:           DWORD iocpKey = 0;
 397:           struct win32iocp_event * event = NULL;
 398:           DWORD lastError = 0;
 399:           isSuccess = GetQueuedCompletionStatus( win32iocp_op->iocp, &bytesTransferred,
 400:                   (DWORD*)&iocpKey, (OVERLAPPED**)&event, 0 );
 401:           lastError = WSAGetLastError();
 402:           if (!isSuccess) {
 403:               if (NULL != event) {
 404:                   if (ERROR_NETNAME_DELETED != lastError) // client abort
 405:                       event_warn ("GetQueuedCompletionStatus failed, errno %d", lastError);
 406:                   if (win32iocp_event_active (win32iocp_op, iocpKey, event) > 0) ++count;
 407:               } else {
 408:                   if (WAIT_TIMEOUT == lastError) {
 409:                       // time-out while waiting for completed I/O request, ignore
 410:                   } else {
 411:                       event_warn ("GetQueuedCompletionStatus failed, errno %d", lastError);
 412:                       return -1;
 413:                   }
 414:               }
 415:               return (count);
 416:           }
 417:           if (NULL == event) {
 418:               event_warn("event is null, dangerous");
 419:               return (count);
 420:           }
 421:           if (win32iocp_event_active (win32iocp_op, iocpKey, event) > 0) ++count;
 422:       }
 423:       return count;
 424:   }
 425:   static int
 426:   win32iocp_dispatch(struct event_base *base, void *arg, struct timeval *tv)
 427:   {
 428:       struct win32iocp_op * win32iocp_op = arg;
 429:       struct win32iocp_entry * entry = NULL;
 430:       int timeout = INFINITE, index = 0, count = 0;
 431:       if (0 != win32iocp_persist_dispatch (win32iocp_op) ) {
 432:           /* has error, and the error events have been actived */
 433:           return 0;
 434:       }
 435:       /* deal with the race condition of one event for multiple OVERLAPPED operations */
 436:       count = win32iocp_event_loop (win32iocp_op);
 437:       if (0 != count) return (count > 0 ? 0 : -1);
 438:       if (tv != NULL)
 439:           timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
 440:       index = WSAWaitForMultipleEvents( MAXIMUM_WAIT_OBJECTS,
 441:               win32iocp_op->objects, FALSE, timeout, FALSE );
 442:       if (WAIT_FAILED == index || WAIT_TIMEOUT == index) {
 443:           if (WAIT_FAILED == index) event_warn("WSAWaitForMultipleEvents");
 444:           return (0);
 445:       }
 446:       index = index - WSA_WAIT_EVENT_0;
 447:       /* event select */
 448:       if (index > 0 ) {
 449:           struct event * event = win32iocp_op->events[index];
 450:           if (NULL != event) {
 451:               WSANETWORKEVENTS net_events;
 452:               int net_errno = 0;
 453:               int ret_event = 0;
 454:               if (SOCKET_ERROR == WSAEnumNetworkEvents (event->ev_fd,
 455:                       win32iocp_op->objects[index], &net_events)) {
 456:                   ret_event = 0;
 457:               } else {
 458:                   if (event->ev_events & EV_CONNECT) {
 459:                       if (net_events.lNetworkEvents & FD_CONNECT) {
 460:                           net_errno = net_events.iErrorCode [FD_CONNECT_BIT];
 461:                           if (0 == net_errno) ret_event = EV_WRITE;
 462:                       }
 463:                   } else {
 464:                       ret_event = event->ev_events & ( EV_READ | EV_WRITE );
 465:                   }
 466:               }
 467:               if (0 == ret_event) {
 468:                   event_warn("win32iocp_dispatch: WSAEnumNetworkEvents fail, errno %d, errcode %d",
 469:                           WSAGetLastError(), net_errno);
 470:               }
 471:               event_active (event, ret_event, 1);
 472:               /* if not persist event, then clear it */
 473:               if( ! (EV_PERSIST & event->ev_events) ) {
 474:                   WSAEventSelect (event->ev_fd, win32iocp_op->objects[index], 0);
 475:                   win32iocp_op->events[index] = NULL;
 476:               }
 477:           }
 478:           return 0;
 479:       }
 480:       /* iocp event */
 481:       if (0 == index ) count = win32iocp_event_loop (win32iocp_op);
 482:       return (count < 0 ? -1 : 0);
 483:   }
 484:   static int
 485:   win32iocp_add(void *arg, struct event *ev)
 486:   {
 487:       struct win32iocp_op * win32iocp_op = arg;
 488:       struct win32iocp_entry * entry = NULL;
 489:       int fd = 0;
 490:       int optval = 0, optlen = sizeof( int );
 491:       if (ev->ev_events & EV_SIGNAL)
 492:           return (evsignal_add(ev));
 493:       fd = ev->ev_fd;
 494:       if (ev->ev_events & EV_CONNECT) {
 495:           return win32iocp_eventselect_add (win32iocp_op, ev, SOCK_STREAM);
 496:       }
 497:       /* Add UDP socket */
 498:       if (SOCKET_ERROR != getsockopt( fd, SOL_SOCKET, SO_TYPE, (char*)&optval, &optlen )) {
 499:           if (SOCK_DGRAM == optval) {
 500:               return win32iocp_eventselect_add (win32iocp_op, ev, SOCK_DGRAM);
 501:           }
 502:       } else {
 503:           event_warn("win32iocp_add: getsockopt fail, errno %d", WSAGetLastError());
 504:           return -1;
 505:       }
 506:       /* Add listen socket */
 507:       if (ev->ev_events & EV_READ) {
 508:           optlen = sizeof( int );
 509:           if (SOCKET_ERROR != getsockopt( fd, SOL_SOCKET, SO_ACCEPTCONN, (char*)&optval, &optlen )) {
 510:               if( optval ) {
 511:                   event_debug(("win32iocp_add: socket(%d) for accept",fd));
 512:                   return win32iocp_eventselect_add( win32iocp_op, ev, SOCK_STREAM);
 513:               }
 514:           } else {
 515:               event_debug(("win32iocp_add: getsockopt fail, errno %d", WSAGetLastError()));
 516:               return -1;
 517:           }
 518:       }
 519:       if (NULL == (entry = win32iocp_get_entry (win32iocp_op, fd, 1)))
 520:           return -1;
 521:       if (0 == entry->nread && 0 == entry->nwrite) {
 522:           if (NULL == CreateIoCompletionPort ((HANDLE)fd, win32iocp_op->iocp, fd, 0) ) {
 523:               /* if ERROR_INVALID_PARAMETER, then this handle was already registered. */
 524:               if (WSAGetLastError() != ERROR_INVALID_PARAMETER) {
 525:                   event_warn("win32iocp_add: CreateIoCompletionPort");
 526:                   return (-1);
 527:               }
 528:           }
 529:       }
 530:       if (ev->ev_events & EV_READ) {
 531:           win32iocp_persist_del (win32iocp_op, ev->ev_fd, EV_READ);
 532:           if (0 == entry->nread) {
 533:               DWORD recvBytes = 0, flags = 0;
 534:               struct win32iocp_event * event = win32iocp_event_new( win32iocp_op );
 535:               if (NULL == event) {
 536:                   event_warn("win32iocp_add: out of memory");
 537:                   return (-1);
 538:               }
 539:               event->event = EV_READ;
 540:               memset( &( event->overlapped ), 0, sizeof( OVERLAPPED ) );
 541:               event->overlapped.hEvent = win32iocp_op->objects[0];
 542:               event->ev = ev;
 543:               if( FALSE == ReadFile( (HANDLE)fd, NULL, 0, &recvBytes, &( event->overlapped ) ) ) {
 544:                   if( ERROR_IO_PENDING != WSAGetLastError() ) {
 545:                       win32iocp_event_free (win32iocp_op, event);
 546:                       event_warn("win32iocp_add: ReadFile failed, errno %d", WSAGetLastError());
 547:                       return (-1);
 548:                   }
 549:               }
 550:               event_debug(("win32iocp_add: register EV_READ for %d", fd));
 551:               entry->nread = 1;
 552:           } else {
 553:               event_debug(("win32iocp_add: readd nonpersist event"));
 554:               return (-1);
 555:           }
 556:       }
 557:       if (ev->ev_events & EV_WRITE) {
 558:           win32iocp_persist_del (win32iocp_op, ev->ev_fd, EV_READ);
 559:           if (0 == entry->nwrite) {
 560:               DWORD sendBytes = 0;
 561:               struct win32iocp_event * event = win32iocp_event_new( win32iocp_op );
 562:               if (NULL == event) {
 563:                   event_warn("win32iocp_add: out of memory");
 564:                   return (-1);
 565:               }
 566:               event->event = EV_WRITE;
 567:               memset( &( event->overlapped ), 0, sizeof( OVERLAPPED ) );
 568:               event->overlapped.hEvent = win32iocp_op->objects[0];
 569:               event->ev = ev;
 570:               if( FALSE == WriteFile( (HANDLE)fd, NULL, 0, &sendBytes, &( event->overlapped ) ) ) {
 571:                   if( ERROR_IO_PENDING != WSAGetLastError() ) {
 572:                       win32iocp_event_free (win32iocp_op, event);
 573:                       event_warn("win32iocp_add: WriteFile failed, errno %d", WSAGetLastError());
 574:                       return (-1);
 575:                   }
 576:               }
 577:               event_debug(("win32iocp_add: register EV_WRITE for %d", fd));
 578:               entry->nwrite = 1;
 579:           } else {
 580:               event_debug(("win32iocp_add: readd nonpersist event"));
 581:               return (-1);
 582:           }
 583:       }
 584:       return (0);
 585:   }
 586:   static int
 587:   win32iocp_del(void *arg, struct event *ev)
 588:   {
 589:       struct win32iocp_op *win32iocp_op = arg;
 590:       struct win32iocp_entry * entry = NULL;
 591:       int fd = 0;
 592:       int optval = 0, optlen = sizeof( int );
 593:       if (ev->ev_events & EV_SIGNAL)
 594:           return (evsignal_del(ev));
 595:       fd = ev->ev_fd;
 596:       if (ev->ev_events & EV_CONNECT)
 597:           return win32iocp_eventselect_del (win32iocp_op, ev);
 598:       /* Del UDP socket */
 599:       if (SOCKET_ERROR != getsockopt( ev->ev_fd, SOL_SOCKET, SO_TYPE, (char*)&optval, &optlen )) {
 600:           if (SOCK_DGRAM == optval) {
 601:               return win32iocp_eventselect_del (win32iocp_op, ev);
 602:           }
 603:       } else {
 604:           event_warn("win32iocp_del: getsockopt fail, errno %d", WSAGetLastError());
 605:           return -1;
 606:       }
 607:       /* Del listen socket */
 608:       if (ev->ev_events & EV_READ) {
 609:           optlen = sizeof( int );
 610:           if (SOCKET_ERROR != getsockopt( ev->ev_fd, SOL_SOCKET, SO_ACCEPTCONN, (char*)&optval, &optlen )) {
 611:               if( optval ) return win32iocp_eventselect_del( win32iocp_op, ev );
 612:           }
 613:       }
 614:  
 615:       entry = win32iocp_get_entry (win32iocp_op, fd, 0);
 616:       if (NULL == entry)
 617:           return (0);
 618:       if (ev->ev_events & EV_READ) {
 619:           win32iocp_persist_del (win32iocp_op, ev->ev_fd, EV_READ);
 620:           entry->nread = 0;
 621:           event_debug(("win32iocp_del: unregister EV_READ for %d", fd));
 622:       }
 623:       if (ev->ev_events & EV_WRITE) {
 624:           win32iocp_persist_del (win32iocp_op, ev->ev_fd, EV_WRITE);
 625:           entry->nwrite = 0;
 626:           event_debug(("win32iocp_del: unregister EV_WRITE for %d", fd));
 627:       }
 628:       if ( ( !entry->nread ) && ( !entry->nwrite ) ) {
 629:           RB_REMOVE(win32iocp_map, &win32iocp_op->event_root, entry);
 630:           free (entry);
 631:       }
 632:       return (0);
 633:   }
 634:   static void
 635:   win32iocp_dealloc(struct event_base *base, void *arg)
 636:   {
 637:       struct win32iocp_op * win32iocp_op = arg;
 638:       struct win32iocp_event * event = NULL, * next = NULL;
 639:       int i = 0;
 640:       evsignal_dealloc(base);
 641:       for (event = win32iocp_op->freelist; NULL != event; ) {
 642:           next = event->next;
 643:           free( event );
 644:           event = next;
 645:       }
 646:       for (event = win32iocp_op->persist; NULL != event; ) {
 647:           next = event->next;
 648:           free( event );
 649:           event = next;
 650:       }
 651:       for (i = 0; i < MAXIMUM_WAIT_OBJECTS; i++) {
 652:           struct event * ev = win32iocp_op->events[i];
 653:           if (NULL != ev) {
 654:               WSAEventSelect (ev->ev_fd, win32iocp_op->objects[i], 0);
 655:           }
 656:           CloseHandle( win32iocp_op->objects[i] );
 657:       }
 658:       if (NULL != win32iocp_op->iocp)
 659:           CloseHandle(win32iocp_op->iocp);
 660:       memset(win32iocp_op, 0, sizeof(struct win32iocp_op));
 661:       free(win32iocp_op);
 662:   }
 663:   #endif

評論: 還須要在 event.h文件中添加 #define EV_CONNECT 0x20 以下: #define EV_TIMEOUT 0x01 #define EV_READ 0x02 #define EV_WRITE 0x04 #define EV_SIGNAL 0x08 #define EV_PERSIST 0x10 /* Persistant event */ #define EV_CONNECT 0x20

相關文章
相關標籤/搜索