epoll.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "iowatcher.h"
  2. #ifdef EVENT_EPOLL
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hevent.h"
  6. #ifdef OS_WIN
  7. #include "wepoll/wepoll.h"
  8. typedef HANDLE epoll_handle_t;
  9. #else
  10. #include <sys/epoll.h>
  11. typedef int epoll_handle_t;
  12. #define epoll_close(epfd) close(epfd)
  13. #endif
  14. #include "array.h"
  15. #define EVENTS_INIT_SIZE 64
  16. ARRAY_DECL(struct epoll_event, events);
  17. typedef struct epoll_ctx_s {
  18. epoll_handle_t epfd;
  19. struct events events;
  20. } epoll_ctx_t;
  21. int iowatcher_init(hloop_t* loop) {
  22. if (loop->iowatcher) return 0;
  23. epoll_ctx_t* epoll_ctx;
  24. HV_ALLOC_SIZEOF(epoll_ctx);
  25. epoll_ctx->epfd = epoll_create(EVENTS_INIT_SIZE);
  26. events_init(&epoll_ctx->events, EVENTS_INIT_SIZE);
  27. loop->iowatcher = epoll_ctx;
  28. return 0;
  29. }
  30. int iowatcher_cleanup(hloop_t* loop) {
  31. if (loop->iowatcher == NULL) return 0;
  32. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  33. epoll_close(epoll_ctx->epfd);
  34. events_cleanup(&epoll_ctx->events);
  35. HV_FREE(loop->iowatcher);
  36. return 0;
  37. }
  38. int iowatcher_add_event(hloop_t* loop, int fd, int events) {
  39. if (loop->iowatcher == NULL) {
  40. iowatcher_init(loop);
  41. }
  42. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  43. hio_t* io = loop->ios.ptr[fd];
  44. struct epoll_event ee;
  45. memset(&ee, 0, sizeof(ee));
  46. ee.data.fd = fd;
  47. // pre events
  48. if (io->events & HV_READ) {
  49. ee.events |= EPOLLIN;
  50. }
  51. if (io->events & HV_WRITE) {
  52. ee.events |= EPOLLOUT;
  53. }
  54. // now events
  55. if (events & HV_READ) {
  56. ee.events |= EPOLLIN;
  57. }
  58. if (events & HV_WRITE) {
  59. ee.events |= EPOLLOUT;
  60. }
  61. int op = io->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD;
  62. epoll_ctl(epoll_ctx->epfd, op, fd, &ee);
  63. if (op == EPOLL_CTL_ADD) {
  64. if (epoll_ctx->events.size == epoll_ctx->events.maxsize) {
  65. events_double_resize(&epoll_ctx->events);
  66. }
  67. epoll_ctx->events.size++;
  68. }
  69. return 0;
  70. }
  71. int iowatcher_del_event(hloop_t* loop, int fd, int events) {
  72. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  73. if (epoll_ctx == NULL) return 0;
  74. hio_t* io = loop->ios.ptr[fd];
  75. struct epoll_event ee;
  76. memset(&ee, 0, sizeof(ee));
  77. ee.data.fd = fd;
  78. // pre events
  79. if (io->events & HV_READ) {
  80. ee.events |= EPOLLIN;
  81. }
  82. if (io->events & HV_WRITE) {
  83. ee.events |= EPOLLOUT;
  84. }
  85. // now events
  86. if (events & HV_READ) {
  87. ee.events &= ~EPOLLIN;
  88. }
  89. if (events & HV_WRITE) {
  90. ee.events &= ~EPOLLOUT;
  91. }
  92. int op = ee.events == 0 ? EPOLL_CTL_DEL : EPOLL_CTL_MOD;
  93. epoll_ctl(epoll_ctx->epfd, op, fd, &ee);
  94. if (op == EPOLL_CTL_DEL) {
  95. epoll_ctx->events.size--;
  96. }
  97. return 0;
  98. }
  99. int iowatcher_poll_events(hloop_t* loop, int timeout) {
  100. epoll_ctx_t* epoll_ctx = (epoll_ctx_t*)loop->iowatcher;
  101. if (epoll_ctx == NULL) return 0;
  102. if (epoll_ctx->events.size == 0) return 0;
  103. int nepoll = epoll_wait(epoll_ctx->epfd, epoll_ctx->events.ptr, epoll_ctx->events.size, timeout);
  104. if (nepoll < 0) {
  105. if (errno == EINTR) {
  106. return 0;
  107. }
  108. perror("epoll");
  109. return nepoll;
  110. }
  111. if (nepoll == 0) return 0;
  112. int nevents = 0;
  113. for (int i = 0; i < epoll_ctx->events.size; ++i) {
  114. struct epoll_event* ee = epoll_ctx->events.ptr + i;
  115. int fd = ee->data.fd;
  116. uint32_t revents = ee->events;
  117. if (revents) {
  118. ++nevents;
  119. hio_t* io = loop->ios.ptr[fd];
  120. if (io) {
  121. if (revents & (EPOLLIN | EPOLLHUP | EPOLLERR)) {
  122. io->revents |= HV_READ;
  123. }
  124. if (revents & (EPOLLOUT | EPOLLHUP | EPOLLERR)) {
  125. io->revents |= HV_WRITE;
  126. }
  127. EVENT_PENDING(io);
  128. }
  129. }
  130. if (nevents == nepoll) break;
  131. }
  132. return nevents;
  133. }
  134. #endif