fdset.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #include <stdlib.h>
  2. #include <unistd.h>
  3. #include <sys/time.h>
  4. #include "dllist.h"
  5. #include "misc.h"
  6. #include "fdset.h"
  7. struct fdset fds[1]; /* global fd list */
  8. int fdset_init(struct fdset *fds)
  9. {
  10. dl_init(fds->list);
  11. fds->del_count = 0;
  12. return 0;
  13. }
  14. int fdset_add_fd(struct fdset *fds, int fd, void *handler, void *data)
  15. {
  16. struct fdset_node *fn;
  17. if (fd < 0)
  18. return -1;
  19. if (handler == 0)
  20. return -1;
  21. for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next)
  22. if (fn->fd == fd)
  23. return -1;
  24. if (not(fn = malloc(sizeof(*fn))))
  25. return -1;
  26. fn->fd = fd;
  27. fn->handler = handler;
  28. fn->data = data;
  29. dl_insert_last(fds->list, fn->node);
  30. return 0;
  31. }
  32. int fdset_del_fd(struct fdset *fds, int fd)
  33. {
  34. struct fdset_node *fn;
  35. for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next)
  36. if (fn->fd == fd)
  37. {
  38. dl_remove(fn->node);
  39. free(fn);
  40. fds->del_count++;
  41. return 0;
  42. }
  43. return -1;
  44. }
  45. int fdset_select(struct fdset *fds, int timeout)
  46. {
  47. struct fdset_node *fn;
  48. fd_set rfds[1];
  49. struct timeval tv[1], *tvp = 0;
  50. int max_fd, x, del_count;
  51. FD_ZERO(rfds);
  52. max_fd = 0;
  53. for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next)
  54. {
  55. FD_SET(fn->fd, rfds);
  56. if (fn->fd >= max_fd)
  57. max_fd = fn->fd + 1;
  58. }
  59. if (timeout >= 0)
  60. {
  61. tv->tv_sec = timeout/1000;
  62. tv->tv_usec = timeout%1000*1000;
  63. tvp = tv;
  64. }
  65. x = select(max_fd, rfds, 0, 0, tvp);
  66. if (x <= 0)
  67. return x;
  68. /* A little bit complicated. A called handler may modify the fdset... */
  69. restart:
  70. del_count = fds->del_count;
  71. for (fn = PTR fds->list->first; fn->node->next; fn = PTR fn->node->next)
  72. if (FD_ISSET(fn->fd, rfds))
  73. {
  74. FD_CLR(fn->fd, rfds);
  75. fn->handler(fn->data, fn->fd);
  76. if (fds->del_count != del_count)
  77. goto restart;
  78. }
  79. return 1;
  80. }