iocp.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #include "iowatcher.h"
  2. #ifdef EVENT_IOCP
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hevent.h"
  6. #include "overlapio.h"
  7. typedef struct iocp_ctx_s {
  8. HANDLE iocp;
  9. } iocp_ctx_t;
  10. int iowatcher_init(hloop_t* loop) {
  11. if (loop->iowatcher) return 0;
  12. iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)malloc(sizeof(iocp_ctx_t));
  13. iocp_ctx->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
  14. loop->iowatcher = iocp_ctx;
  15. return 0;
  16. }
  17. int iowatcher_cleanup(hloop_t* loop) {
  18. if (loop->iowatcher == NULL) return 0;
  19. iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
  20. CloseHandle(iocp_ctx->iocp);
  21. SAFE_FREE(loop->iowatcher);
  22. return 0;
  23. }
  24. int iowatcher_add_event(hloop_t* loop, int fd, int events) {
  25. if (loop->iowatcher == NULL) {
  26. iowatcher_init(loop);
  27. }
  28. iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
  29. hio_t* io = loop->ios.ptr[fd];
  30. if (io && io->events == 0 && events != 0) {
  31. CreateIoCompletionPort((HANDLE)fd, iocp_ctx->iocp, 0, 0);
  32. }
  33. return 0;
  34. }
  35. int iowatcher_del_event(hloop_t* loop, int fd, int events) {
  36. hio_t* io = loop->ios.ptr[fd];
  37. if ((io->events & ~events) == 0) {
  38. CancelIo((HANDLE)fd);
  39. }
  40. return 0;
  41. }
  42. int iowatcher_poll_events(hloop_t* loop, int timeout) {
  43. if (loop->iowatcher == NULL) return 0;
  44. iocp_ctx_t* iocp_ctx = (iocp_ctx_t*)loop->iowatcher;
  45. DWORD bytes = 0;
  46. ULONG_PTR key = 0;
  47. LPOVERLAPPED povlp = NULL;
  48. BOOL bRet = GetQueuedCompletionStatus(iocp_ctx->iocp, &bytes, &key, &povlp, timeout);
  49. int err = 0;
  50. if (povlp == NULL) {
  51. err = WSAGetLastError();
  52. if (err == WAIT_TIMEOUT || ERROR_NETNAME_DELETED || ERROR_OPERATION_ABORTED) {
  53. return 0;
  54. }
  55. return -err;
  56. }
  57. hoverlapped_t* hovlp = (hoverlapped_t*)povlp;
  58. hio_t* io = hovlp->io;
  59. if (bRet == FALSE) {
  60. err = WSAGetLastError();
  61. printd("iocp ret=%d err=%d bytes=%u\n", bRet, err, bytes);
  62. // NOTE: when ConnectEx failed, err != 0
  63. hovlp->error = err;
  64. }
  65. // NOTE: when WSASend/WSARecv disconnect, bytes = 0
  66. hovlp->bytes = bytes;
  67. io->hovlp = hovlp;
  68. io->revents |= hovlp->event;
  69. EVENT_PENDING(hovlp->io);
  70. return 1;
  71. }
  72. #endif