evport.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include "iowatcher.h"
  2. #ifdef EVENT_PORT
  3. #include "hplatform.h"
  4. #include "hdef.h"
  5. #include "hevent.h"
  6. #include <port.h>
  7. #define EVENTS_INIT_SIZE 64
  8. typedef struct evport_ctx_s {
  9. int port;
  10. int capacity;
  11. int nevents;
  12. port_event_t* events;
  13. } evport_ctx_t;
  14. static void evport_ctx_resize(evport_ctx_t* evport_ctx, int size) {
  15. int bytes = sizeof(port_event_t) * size;
  16. int oldbytes = sizeof(port_event_t) * evport_ctx->capacity;
  17. evport_ctx->events = (port_event_t*)hv_realloc(evport_ctx->events, bytes, oldbytes);
  18. evport_ctx->capacity = size;
  19. }
  20. int iowatcher_init(hloop_t* loop) {
  21. if (loop->iowatcher) return 0;
  22. evport_ctx_t* evport_ctx;
  23. HV_ALLOC_SIZEOF(evport_ctx);
  24. evport_ctx->port = port_create();
  25. evport_ctx->capacity = EVENTS_INIT_SIZE;
  26. evport_ctx->nevents = 0;
  27. int bytes = sizeof(port_event_t) * evport_ctx->capacity;
  28. HV_ALLOC(evport_ctx->events, bytes);
  29. loop->iowatcher = evport_ctx;
  30. return 0;
  31. }
  32. int iowatcher_cleanup(hloop_t* loop) {
  33. if (loop->iowatcher == NULL) return 0;
  34. evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher;
  35. close(evport_ctx->port);
  36. HV_FREE(evport_ctx->events);
  37. HV_FREE(loop->iowatcher);
  38. return 0;
  39. }
  40. int iowatcher_add_event(hloop_t* loop, int fd, int events) {
  41. if (loop->iowatcher == NULL) {
  42. iowatcher_init(loop);
  43. }
  44. evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher;
  45. hio_t* io = loop->ios.ptr[fd];
  46. int evport_events = 0;
  47. if (io->events & HV_READ) {
  48. evport_events |= POLLIN;
  49. }
  50. if (io->events & HV_WRITE) {
  51. evport_events |= POLLOUT;
  52. }
  53. if (events & HV_READ) {
  54. evport_events |= POLLIN;
  55. }
  56. if (events & HV_WRITE) {
  57. evport_events |= POLLOUT;
  58. }
  59. port_associate(evport_ctx->port, PORT_SOURCE_FD, fd, evport_events, NULL);
  60. if (io->events == 0) {
  61. if (evport_ctx->nevents == evport_ctx->capacity) {
  62. evport_ctx_resize(evport_ctx, evport_ctx->capacity * 2);
  63. }
  64. ++evport_ctx->nevents;
  65. }
  66. return 0;
  67. }
  68. int iowatcher_del_event(hloop_t* loop, int fd, int events) {
  69. evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher;
  70. if (evport_ctx == NULL) return 0;
  71. hio_t* io = loop->ios.ptr[fd];
  72. int evport_events = 0;
  73. if (io->events & HV_READ) {
  74. evport_events |= POLLIN;
  75. }
  76. if (io->events & HV_WRITE) {
  77. evport_events |= POLLOUT;
  78. }
  79. if (events & HV_READ) {
  80. evport_events &= ~POLLIN;
  81. }
  82. if (events & HV_WRITE) {
  83. evport_events &= ~POLLOUT;
  84. }
  85. if (evport_events == 0) {
  86. port_dissociate(evport_ctx->port, PORT_SOURCE_FD, fd);
  87. --evport_ctx->nevents;
  88. } else {
  89. port_associate(evport_ctx->port, PORT_SOURCE_FD, fd, evport_events, NULL);
  90. }
  91. return 0;
  92. }
  93. int iowatcher_poll_events(hloop_t* loop, int timeout) {
  94. evport_ctx_t* evport_ctx = (evport_ctx_t*)loop->iowatcher;
  95. if (evport_ctx == NULL) return 0;
  96. struct timespec ts, *tp;
  97. if (timeout == INFINITE) {
  98. tp = NULL;
  99. } else {
  100. ts.tv_sec = timeout / 1000;
  101. ts.tv_nsec = (timeout % 1000) * 1000000;
  102. tp = &ts;
  103. }
  104. unsigned nevents = 1;
  105. port_getn(evport_ctx->port, evport_ctx->events, evport_ctx->capacity, &nevents, tp);
  106. for (int i = 0; i < nevents; ++i) {
  107. int fd = evport_ctx->events[i].portev_object;
  108. int revents = evport_ctx->events[i].portev_events;
  109. hio_t* io = loop->ios.ptr[fd];
  110. if (io) {
  111. if (revents & POLLIN) {
  112. io->revents |= HV_READ;
  113. }
  114. if (revents & POLLOUT) {
  115. io->revents |= HV_WRITE;
  116. }
  117. EVENT_PENDING(io);
  118. }
  119. // Upon retrieval, the event object is no longer associated with the port.
  120. iowatcher_add_event(loop, fd, io->events);
  121. }
  122. return nevents;
  123. }
  124. #endif