mirror of
https://github.com/cuberite/libevent.git
synced 2025-08-04 01:36:23 -04:00
Refactor IOCP callback interface
Chris Davis points out that GetQueuedCompletionStatus sometimes returns false not to report "No events for you!" but instead to report "An overlapped operation failed." Add a way to tell an event_overlapped that its operation failed. svn:r1490
This commit is contained in:
parent
9a772148f2
commit
a84c87d76a
@ -111,7 +111,7 @@ pin_release(struct event_overlapped *eo, unsigned flag)
|
||||
|
||||
/** IOCP callback invoked when a read operation is finished. */
|
||||
static void
|
||||
read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
|
||||
read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes, int ok)
|
||||
{
|
||||
struct buffer_overlapped *buf_o = upcast_overlapped(eo);
|
||||
struct evbuffer_overlapped *buf = buf_o->buf;
|
||||
@ -120,6 +120,8 @@ read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
|
||||
struct evbuffer_iovec iov[2];
|
||||
int n_vec;
|
||||
|
||||
// XXXX use ok
|
||||
|
||||
EVBUFFER_LOCK(evbuf, EVTHREAD_WRITE);
|
||||
buf->read_in_progress = 0;
|
||||
evbuffer_unfreeze(evbuf, 0);
|
||||
@ -145,8 +147,9 @@ read_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
|
||||
|
||||
/** IOCP callback invoked when a write operation is finished. */
|
||||
static void
|
||||
write_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes)
|
||||
write_completed(struct event_overlapped *eo, uintptr_t _, ev_ssize_t nBytes, int ok)
|
||||
{
|
||||
// XXX use ok
|
||||
struct buffer_overlapped *buf_o = upcast_overlapped(eo);
|
||||
struct evbuffer_overlapped *buf = buf_o->buf;
|
||||
|
||||
|
21
event_iocp.c
21
event_iocp.c
@ -47,28 +47,29 @@ event_overlapped_init(struct event_overlapped *o, iocp_callback cb)
|
||||
}
|
||||
|
||||
static void
|
||||
handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes)
|
||||
handle_entry(OVERLAPPED *o, ULONG_PTR completion_key, DWORD nBytes, int ok)
|
||||
{
|
||||
struct event_overlapped *eo =
|
||||
EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
|
||||
eo->cb(eo, completion_key, nBytes);
|
||||
eo->cb(eo, completion_key, nBytes, ok);
|
||||
}
|
||||
|
||||
static void
|
||||
loop(void *_port)
|
||||
{
|
||||
struct event_iocp_port *port = _port;
|
||||
OVERLAPPED *overlapped;
|
||||
ULONG_PTR key;
|
||||
DWORD bytes;
|
||||
long ms = port->ms;
|
||||
HANDLE p = port->port;
|
||||
|
||||
if (ms <= 0)
|
||||
ms = INFINITE;
|
||||
|
||||
while (GetQueuedCompletionStatus(p, &bytes, &key,
|
||||
&overlapped, ms)) {
|
||||
while (1) {
|
||||
OVERLAPPED *overlapped=NULL;
|
||||
ULONG_PTR key=0;
|
||||
DWORD bytes=0;
|
||||
int ok = GetQueuedCompletionStatus(p, &bytes, &key,
|
||||
&overlapped, ms);
|
||||
EnterCriticalSection(&port->lock);
|
||||
if (port->shutdown) {
|
||||
if (--port->n_live_threads == 0)
|
||||
@ -78,8 +79,10 @@ loop(void *_port)
|
||||
}
|
||||
LeaveCriticalSection(&port->lock);
|
||||
|
||||
if (key != NOTIFICATION_KEY)
|
||||
handle_entry(overlapped, key, bytes);
|
||||
if (key != NOTIFICATION_KEY && overlapped)
|
||||
handle_entry(overlapped, key, bytes, ok);
|
||||
else if (!overlapped)
|
||||
break;
|
||||
}
|
||||
event_warnx("GetQueuedCompletionStatus exited with no event.");
|
||||
EnterCriticalSection(&port->lock);
|
||||
|
@ -34,7 +34,7 @@ extern "C" {
|
||||
struct event_overlapped;
|
||||
struct event_iocp_port;
|
||||
struct evbuffer;
|
||||
typedef void (*iocp_callback)(struct event_overlapped *, uintptr_t, ev_ssize_t);
|
||||
typedef void (*iocp_callback)(struct event_overlapped *, uintptr_t, ev_ssize_t, int success);
|
||||
|
||||
/* This whole file is actually win32 only. We wrap the structures in a win32
|
||||
* ifdef so that we can test-compile code that uses these interfaces on
|
||||
|
@ -297,7 +297,7 @@ struct accepting_socket {
|
||||
};
|
||||
|
||||
static void accepted_socket_cb(struct event_overlapped *o, uintptr_t key,
|
||||
ev_ssize_t n);
|
||||
ev_ssize_t n, int ok);
|
||||
|
||||
static struct accepting_socket *
|
||||
new_accepting_socket(struct evconnlistener_iocp *lev, int family)
|
||||
@ -370,7 +370,7 @@ start_accepting(struct accepting_socket *as)
|
||||
as->buflen/2, as->buflen/2,
|
||||
&pending, &as->overlapped.overlapped)) {
|
||||
/* Immediate success! */
|
||||
accepted_socket_cb(&as->overlapped, 1, 0);
|
||||
accepted_socket_cb(&as->overlapped, 1, 0, 1);
|
||||
result = 0;
|
||||
} else {
|
||||
int err = WSAGetLastError();
|
||||
@ -395,10 +395,11 @@ stop_accepting(struct accepting_socket *as)
|
||||
#endif
|
||||
|
||||
static void
|
||||
accepted_socket_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n)
|
||||
accepted_socket_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n, int ok)
|
||||
{
|
||||
/* Run this whole thing deferred unless some MT flag is set */
|
||||
/* XXX needs locking. */
|
||||
/* XXX use ok */
|
||||
|
||||
struct sockaddr *sa_local=NULL, *sa_remote=NULL;
|
||||
int socklen_local=0, socklen_remote=0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user