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