1
0

select.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include "iowatcher.h"
  2. #ifdef EVENT_SELECT
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hevent.h"
  6. #include "hsocket.h"
  7. typedef struct select_ctx_s {
  8. int max_fd;
  9. fd_set readfds;
  10. fd_set writefds;
  11. int nread;
  12. int nwrite;
  13. } select_ctx_t;
  14. int iowatcher_init(hloop_t* loop) {
  15. if (loop->iowatcher) return 0;
  16. select_ctx_t* select_ctx;
  17. HV_ALLOC_SIZEOF(select_ctx);
  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->iowatcher = select_ctx;
  24. return 0;
  25. }
  26. int iowatcher_cleanup(hloop_t* loop) {
  27. HV_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. select_ctx_t* select_ctx = (select_ctx_t*)loop->iowatcher;
  35. if (fd > select_ctx->max_fd) {
  36. select_ctx->max_fd = fd;
  37. }
  38. if (events & HV_READ) {
  39. if (!FD_ISSET(fd, &select_ctx->readfds)) {
  40. FD_SET(fd, &select_ctx->readfds);
  41. select_ctx->nread++;
  42. }
  43. }
  44. if (events & HV_WRITE) {
  45. if (!FD_ISSET(fd, &select_ctx->writefds)) {
  46. FD_SET(fd, &select_ctx->writefds);
  47. select_ctx->nwrite++;
  48. }
  49. }
  50. return 0;
  51. }
  52. int iowatcher_del_event(hloop_t* loop, int fd, int events) {
  53. select_ctx_t* select_ctx = (select_ctx_t*)loop->iowatcher;
  54. if (select_ctx == NULL) return 0;
  55. if (fd == select_ctx->max_fd) {
  56. select_ctx->max_fd = -1;
  57. }
  58. if (events & HV_READ) {
  59. if (FD_ISSET(fd, &select_ctx->readfds)) {
  60. FD_CLR(fd, &select_ctx->readfds);
  61. select_ctx->nread--;
  62. }
  63. }
  64. if (events & HV_WRITE) {
  65. if (FD_ISSET(fd, &select_ctx->writefds)) {
  66. FD_CLR(fd, &select_ctx->writefds);
  67. select_ctx->nwrite--;
  68. }
  69. }
  70. return 0;
  71. }
  72. static int find_max_active_fd(hloop_t* loop) {
  73. hio_t* io = NULL;
  74. for (int i = loop->ios.maxsize-1; i >= 0; --i) {
  75. io = loop->ios.ptr[i];
  76. if (io && io->active && io->events) return i;
  77. }
  78. return -1;
  79. }
  80. static int remove_bad_fds(hloop_t* loop) {
  81. select_ctx_t* select_ctx = (select_ctx_t*)loop->iowatcher;
  82. if (select_ctx == NULL) return 0;
  83. int badfds = 0;
  84. int error = 0;
  85. socklen_t optlen = sizeof(error);
  86. for (int fd = 0; fd <= select_ctx->max_fd; ++fd) {
  87. if (FD_ISSET(fd, &select_ctx->readfds) ||
  88. FD_ISSET(fd, &select_ctx->writefds)) {
  89. error = 0;
  90. optlen = sizeof(int);
  91. if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&error, &optlen) < 0 || error != 0) {
  92. ++badfds;
  93. hio_t* io = loop->ios.ptr[fd];
  94. if (io) {
  95. hio_del(io, HV_RDWR);
  96. }
  97. }
  98. }
  99. }
  100. return badfds;
  101. }
  102. int iowatcher_poll_events(hloop_t* loop, int timeout) {
  103. select_ctx_t* select_ctx = (select_ctx_t*)loop->iowatcher;
  104. if (select_ctx == NULL) return 0;
  105. if (select_ctx->nread == 0 && select_ctx->nwrite == 0) {
  106. return 0;
  107. }
  108. int max_fd = select_ctx->max_fd;
  109. fd_set readfds = select_ctx->readfds;
  110. fd_set writefds = select_ctx->writefds;
  111. if (max_fd == -1) {
  112. select_ctx->max_fd = max_fd = find_max_active_fd(loop);
  113. }
  114. struct timeval tv, *tp;
  115. if (timeout == INFINITE) {
  116. tp = NULL;
  117. }
  118. else {
  119. tv.tv_sec = timeout / 1000;
  120. tv.tv_usec = (timeout % 1000) * 1000;
  121. tp = &tv;
  122. }
  123. int nselect = select(max_fd+1, &readfds, &writefds, NULL, tp);
  124. if (nselect < 0) {
  125. #ifdef OS_WIN
  126. if (WSAGetLastError() == WSAENOTSOCK) {
  127. #else
  128. if (errno == EBADF) {
  129. perror("select");
  130. #endif
  131. remove_bad_fds(loop);
  132. return -EBADF;
  133. }
  134. return nselect;
  135. }
  136. if (nselect == 0) return 0;
  137. int nevents = 0;
  138. int revents = 0;
  139. for (int fd = 0; fd <= max_fd; ++fd) {
  140. revents = 0;
  141. if (FD_ISSET(fd, &readfds)) {
  142. ++nevents;
  143. revents |= HV_READ;
  144. }
  145. if (FD_ISSET(fd, &writefds)) {
  146. ++nevents;
  147. revents |= HV_WRITE;
  148. }
  149. if (revents) {
  150. hio_t* io = loop->ios.ptr[fd];
  151. if (io) {
  152. io->revents = revents;
  153. EVENT_PENDING(io);
  154. }
  155. }
  156. if (nevents == nselect) break;
  157. }
  158. return nevents;
  159. }
  160. #endif