epoll.c 3.6 KB

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