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. */
|
/** IOCP callback invoked when a read operation is finished. */
|
||||||
static void
|
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 buffer_overlapped *buf_o = upcast_overlapped(eo);
|
||||||
struct evbuffer_overlapped *buf = buf_o->buf;
|
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];
|
struct evbuffer_iovec iov[2];
|
||||||
int n_vec;
|
int n_vec;
|
||||||
|
|
||||||
|
// XXXX use ok
|
||||||
|
|
||||||
EVBUFFER_LOCK(evbuf, EVTHREAD_WRITE);
|
EVBUFFER_LOCK(evbuf, EVTHREAD_WRITE);
|
||||||
buf->read_in_progress = 0;
|
buf->read_in_progress = 0;
|
||||||
evbuffer_unfreeze(evbuf, 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. */
|
/** IOCP callback invoked when a write operation is finished. */
|
||||||
static void
|
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 buffer_overlapped *buf_o = upcast_overlapped(eo);
|
||||||
struct evbuffer_overlapped *buf = buf_o->buf;
|
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
|
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 =
|
struct event_overlapped *eo =
|
||||||
EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
|
EVUTIL_UPCAST(o, struct event_overlapped, overlapped);
|
||||||
eo->cb(eo, completion_key, nBytes);
|
eo->cb(eo, completion_key, nBytes, ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
loop(void *_port)
|
loop(void *_port)
|
||||||
{
|
{
|
||||||
struct event_iocp_port *port = _port;
|
struct event_iocp_port *port = _port;
|
||||||
OVERLAPPED *overlapped;
|
|
||||||
ULONG_PTR key;
|
|
||||||
DWORD bytes;
|
|
||||||
long ms = port->ms;
|
long ms = port->ms;
|
||||||
HANDLE p = port->port;
|
HANDLE p = port->port;
|
||||||
|
|
||||||
if (ms <= 0)
|
if (ms <= 0)
|
||||||
ms = INFINITE;
|
ms = INFINITE;
|
||||||
|
|
||||||
while (GetQueuedCompletionStatus(p, &bytes, &key,
|
while (1) {
|
||||||
&overlapped, ms)) {
|
OVERLAPPED *overlapped=NULL;
|
||||||
|
ULONG_PTR key=0;
|
||||||
|
DWORD bytes=0;
|
||||||
|
int ok = GetQueuedCompletionStatus(p, &bytes, &key,
|
||||||
|
&overlapped, ms);
|
||||||
EnterCriticalSection(&port->lock);
|
EnterCriticalSection(&port->lock);
|
||||||
if (port->shutdown) {
|
if (port->shutdown) {
|
||||||
if (--port->n_live_threads == 0)
|
if (--port->n_live_threads == 0)
|
||||||
@ -78,8 +79,10 @@ loop(void *_port)
|
|||||||
}
|
}
|
||||||
LeaveCriticalSection(&port->lock);
|
LeaveCriticalSection(&port->lock);
|
||||||
|
|
||||||
if (key != NOTIFICATION_KEY)
|
if (key != NOTIFICATION_KEY && overlapped)
|
||||||
handle_entry(overlapped, key, bytes);
|
handle_entry(overlapped, key, bytes, ok);
|
||||||
|
else if (!overlapped)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
event_warnx("GetQueuedCompletionStatus exited with no event.");
|
event_warnx("GetQueuedCompletionStatus exited with no event.");
|
||||||
EnterCriticalSection(&port->lock);
|
EnterCriticalSection(&port->lock);
|
||||||
|
@ -34,7 +34,7 @@ extern "C" {
|
|||||||
struct event_overlapped;
|
struct event_overlapped;
|
||||||
struct event_iocp_port;
|
struct event_iocp_port;
|
||||||
struct evbuffer;
|
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
|
/* 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
|
* 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,
|
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 *
|
static struct accepting_socket *
|
||||||
new_accepting_socket(struct evconnlistener_iocp *lev, int family)
|
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,
|
as->buflen/2, as->buflen/2,
|
||||||
&pending, &as->overlapped.overlapped)) {
|
&pending, &as->overlapped.overlapped)) {
|
||||||
/* Immediate success! */
|
/* Immediate success! */
|
||||||
accepted_socket_cb(&as->overlapped, 1, 0);
|
accepted_socket_cb(&as->overlapped, 1, 0, 1);
|
||||||
result = 0;
|
result = 0;
|
||||||
} else {
|
} else {
|
||||||
int err = WSAGetLastError();
|
int err = WSAGetLastError();
|
||||||
@ -395,10 +395,11 @@ stop_accepting(struct accepting_socket *as)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
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 */
|
/* Run this whole thing deferred unless some MT flag is set */
|
||||||
/* XXX needs locking. */
|
/* XXX needs locking. */
|
||||||
|
/* XXX use ok */
|
||||||
|
|
||||||
struct sockaddr *sa_local=NULL, *sa_remote=NULL;
|
struct sockaddr *sa_local=NULL, *sa_remote=NULL;
|
||||||
int socklen_local=0, socklen_remote=0;
|
int socklen_local=0, socklen_remote=0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user