epoll.c 3.8 KB

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