82 lines
2.2 KiB
C
82 lines
2.2 KiB
C
|
#include "iowatcher.h"
|
||
|
|
||
|
#ifdef EVENT_IOCP
|
||
|
#include "hplatform.h"
|
||
|
#include "hdef.h"
|
||
|
|
||
|
#include "hevent.h"
|
||
|
#include "overlapio.h"
|
||
|
|
||
|
typedef struct iocp_ctx_s {
|
||
|
HANDLE iocp;
|
||
|
} iocp_ctx_t;
|
||
|
|
||
|
int iowatcher_init(hloop_t* loop) {
|
||
|
if (loop->iowatcher) return 0;
|
||
|
iocp_ctx_t* iocp_ctx;
|
||
|
HV_ALLOC_SIZEOF(iocp_ctx);
|
||
|
iocp_ctx->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
||
|
loop->iowatcher = iocp_ctx;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iowatcher_cleanup(hloop_t* loop) {
|
||
|
if (loop->iowatcher == NULL) return 0;
|
||
|
iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
|
||
|
CloseHandle(iocp_ctx->iocp);
|
||
|
HV_FREE(loop->iowatcher);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iowatcher_add_event(hloop_t* loop, int fd, int events) {
|
||
|
if (loop->iowatcher == NULL) {
|
||
|
iowatcher_init(loop);
|
||
|
}
|
||
|
iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
|
||
|
hio_t* io = loop->ios.ptr[fd];
|
||
|
if (io && io->events == 0 && events != 0) {
|
||
|
CreateIoCompletionPort((HANDLE)fd, iocp_ctx->iocp, 0, 0);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iowatcher_del_event(hloop_t* loop, int fd, int events) {
|
||
|
hio_t* io = loop->ios.ptr[fd];
|
||
|
if ((io->events & ~events) == 0) {
|
||
|
CancelIo((HANDLE)fd);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int iowatcher_poll_events(hloop_t* loop, int timeout) {
|
||
|
if (loop->iowatcher == NULL) return 0;
|
||
|
iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
|
||
|
DWORD bytes = 0;
|
||
|
ULONG_PTR key = 0;
|
||
|
LPOVERLAPPED povlp = NULL;
|
||
|
BOOL bRet = GetQueuedCompletionStatus(iocp_ctx->iocp, &bytes, &key, &povlp, timeout);
|
||
|
int err = 0;
|
||
|
if (povlp == NULL) {
|
||
|
err = WSAGetLastError();
|
||
|
if (err == WAIT_TIMEOUT || ERROR_NETNAME_DELETED || ERROR_OPERATION_ABORTED) {
|
||
|
return 0;
|
||
|
}
|
||
|
return -err;
|
||
|
}
|
||
|
hoverlapped_t* hovlp = (hoverlapped_t*)povlp;
|
||
|
hio_t* io = hovlp->io;
|
||
|
if (bRet == FALSE) {
|
||
|
err = WSAGetLastError();
|
||
|
printd("iocp ret=%d err=%d bytes=%u\n", bRet, err, bytes);
|
||
|
// NOTE: when ConnectEx failed, err != 0
|
||
|
hovlp->error = err;
|
||
|
}
|
||
|
// NOTE: when WSASend/WSARecv disconnect, bytes = 0
|
||
|
hovlp->bytes = bytes;
|
||
|
io->hovlp = hovlp;
|
||
|
io->revents |= hovlp->event;
|
||
|
EVENT_PENDING(hovlp->io);
|
||
|
return 1;
|
||
|
}
|
||
|
#endif
|