select.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "hevent.h"
  2. #ifdef EVENT_SELECT
  3. #include "hplatform.h"
  4. #ifdef OS_LINUX
  5. #include <sys/select.h>
  6. #endif
  7. #include "hdef.h"
  8. typedef struct select_ctx_s {
  9. int max_fd;
  10. fd_set readfds;
  11. fd_set writefds;
  12. int nread;
  13. int nwrite;
  14. } select_ctx_t;
  15. int _event_init(hloop_t* loop) {
  16. if (loop->event_ctx) return 0;
  17. select_ctx_t* select_ctx = (select_ctx_t*)malloc(sizeof(select_ctx_t));
  18. select_ctx->max_fd = -1;
  19. FD_ZERO(&select_ctx->readfds);
  20. FD_ZERO(&select_ctx->writefds);
  21. select_ctx->nread = 0;
  22. select_ctx->nwrite = 0;
  23. loop->event_ctx = select_ctx;
  24. return 0;
  25. }
  26. int _event_cleanup(hloop_t* loop) {
  27. SAFE_FREE(loop->event_ctx);
  28. return 0;
  29. }
  30. int _add_event(hevent_t* event, int type) {
  31. hloop_t* loop = event->loop;
  32. if (loop->event_ctx == NULL) {
  33. hloop_event_init(loop);
  34. }
  35. select_ctx_t* select_ctx = (select_ctx_t*)loop->event_ctx;
  36. int fd = event->fd;
  37. if (fd > select_ctx->max_fd) {
  38. select_ctx->max_fd = fd;
  39. }
  40. if (type & READ_EVENT) {
  41. if (!FD_ISSET(fd, &select_ctx->readfds)) {
  42. FD_SET(fd, &select_ctx->readfds);
  43. select_ctx->nread++;
  44. }
  45. }
  46. if (type & WRITE_EVENT) {
  47. if (!FD_ISSET(fd, &select_ctx->writefds)) {
  48. FD_SET(fd, &select_ctx->writefds);
  49. select_ctx->nwrite++;
  50. }
  51. }
  52. return 0;
  53. }
  54. int _del_event(hevent_t* event, int type) {
  55. hloop_t* loop = event->loop;
  56. select_ctx_t* select_ctx = (select_ctx_t*)loop->event_ctx;
  57. if (select_ctx == NULL) return 0;
  58. int fd = event->fd;
  59. if (fd == select_ctx->max_fd) {
  60. select_ctx->max_fd = -1;
  61. }
  62. if (type & READ_EVENT) {
  63. if (FD_ISSET(fd, &select_ctx->readfds)) {
  64. FD_CLR(fd, &select_ctx->readfds);
  65. select_ctx->nread--;
  66. }
  67. }
  68. if (type & WRITE_EVENT) {
  69. if (FD_ISSET(fd, &select_ctx->writefds)) {
  70. FD_CLR(fd, &select_ctx->writefds);
  71. select_ctx->nwrite--;
  72. }
  73. }
  74. return 0;
  75. }
  76. int _handle_events(hloop_t* loop, int timeout) {
  77. select_ctx_t* select_ctx = (select_ctx_t*)loop->event_ctx;
  78. if (select_ctx == NULL) return 0;
  79. if (select_ctx->nread == 0 && select_ctx->nwrite == 0) {
  80. return 0;
  81. }
  82. int max_fd = select_ctx->max_fd;
  83. fd_set readfds = select_ctx->readfds;
  84. fd_set writefds = select_ctx->writefds;
  85. if (max_fd == -1) {
  86. for (auto& pair : loop->events) {
  87. int fd = pair.first;
  88. if (fd > max_fd) {
  89. max_fd = fd;
  90. }
  91. }
  92. select_ctx->max_fd = max_fd;
  93. }
  94. struct timeval tv, *tp;
  95. if (timeout == INFINITE) {
  96. tp = NULL;
  97. }
  98. else {
  99. tv.tv_sec = timeout / 1000;
  100. tv.tv_usec = (timeout % 1000) * 1000;
  101. tp = &tv;
  102. }
  103. int nselect = select(max_fd+1, &readfds, &writefds, NULL, tp);
  104. if (nselect < 0) {
  105. #ifdef OS_WIN
  106. if (WSAGetLastError() == WSAENOTSOCK) {
  107. #else
  108. if (errno == EBADF) {
  109. perror("select");
  110. #endif
  111. return -EBADF;
  112. }
  113. return nselect;
  114. }
  115. if (nselect == 0) return 0;
  116. int nevent = 0;
  117. auto iter = loop->events.begin();
  118. while (iter != loop->events.end()) {
  119. if (nevent == nselect) break;
  120. int fd = iter->first;
  121. hevent_t* event = iter->second;
  122. if (FD_ISSET(fd, &readfds)) {
  123. ++nevent;
  124. _on_read(event);
  125. }
  126. if (FD_ISSET(fd, &writefds)) {
  127. ++nevent;
  128. _on_write(event);
  129. }
  130. ++iter;
  131. }
  132. return nevent;
  133. }
  134. #endif