select.cpp 3.6 KB

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