iocp.c 2.2 KB

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