让Libevent 在window下 支持 IOCP

Libevent 的强大就不说了,但由于在window下使用的是 select 机制 ,除了效率低下意外还有一个讨厌的"FD_SETSIZE"限制,所以一直 希望能支持IOCP,可是现在已经到2.0还是没能够支持。


无意中在网上发现了个支持IOCP的libevent版本,是1.4.7版的。不过没关系,把其中的一个关键文件"win32iocp.c"拷贝到最新的1.4.14b版本中,并在"event.c" 中修改:

.....
#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;
#endif

.....

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 WIN32

#ifndef _EVENT_NOIOCP
&win32iocpops,
#endif

&win32ops,
#endif
NULL
};

....


红色部分是添加的。

这样就可以很好的支持IOCP了。


附: win32iocp.c 代码

   1:    /*
   2:     * win32iocp.c
   3:     *
   4:     * Integerate Windows I/O Completion Port into Libevent.
   5:     *
   6:     * Submitted by Stephen Liu <[email protected]>
   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

你可能感兴趣的:(让Libevent 在window下 支持 IOCP)