kqueue.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #include "hevent.h"
  2. #ifdef EVENT_KQUEUE
  3. #include "hplatform.h"
  4. #if defined(OS_MAC) || defined(OS_BSD)
  5. #include <sys/event.h>
  6. #endif
  7. #include "hdef.h"
  8. #define INIT_EVENTS_NUM 64
  9. typedef struct kqueue_ctx_s {
  10. int kqfd;
  11. int capacity;
  12. int nchanges;
  13. struct kevent* changes;
  14. //int nevents; // nevents == nchanges
  15. struct kevent* events;
  16. } kqueue_ctx_t;
  17. static void kqueue_ctx_resize(kqueue_ctx_t* kqueue_ctx, int size) {
  18. int bytes = sizeof(struct kevent) * size;
  19. kqueue_ctx->changes = (struct kevent*)realloc(kqueue_ctx->changes, bytes);
  20. kqueue_ctx->events = (struct kevent*)realloc(kqueue_ctx->events, bytes);
  21. kqueue_ctx->capacity = size;
  22. }
  23. int _event_init(hloop_t* loop) {
  24. if (loop->event_ctx) return 0;
  25. kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)malloc(sizeof(kqueue_ctx_t));
  26. kqueue_ctx->kqfd = kqueue();
  27. kqueue_ctx->capacity = INIT_EVENTS_NUM;
  28. kqueue_ctx->nchanges = 0;
  29. int bytes = sizeof(struct kevent) * kqueue_ctx->capacity;
  30. kqueue_ctx->changes = (struct kevent*)malloc(bytes);
  31. memset(kqueue_ctx->changes, 0, bytes);
  32. kqueue_ctx->events = (struct kevent*)malloc(bytes);
  33. memset(kqueue_ctx->events, 0, bytes);
  34. loop->event_ctx = kqueue_ctx;
  35. return 0;
  36. }
  37. int _event_cleanup(hloop_t* loop) {
  38. if (loop->event_ctx == NULL) return 0;
  39. kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)loop->event_ctx;
  40. close(kqueue_ctx->kqfd);
  41. SAFE_FREE(kqueue_ctx->changes);
  42. SAFE_FREE(kqueue_ctx->events);
  43. SAFE_FREE(loop->event_ctx);
  44. return 0;
  45. }
  46. static int __add_event(hevent_t* event, int type) {
  47. hloop_t* loop = event->loop;
  48. if (loop->event_ctx == NULL) {
  49. hloop_event_init(loop);
  50. }
  51. kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)loop->event_ctx;
  52. int idx = event->event_index[EVENT_INDEX(type)];
  53. if (idx < 0) {
  54. event->event_index[EVENT_INDEX(type)] = idx = kqueue_ctx->nchanges;
  55. kqueue_ctx->nchanges++;
  56. if (idx == kqueue_ctx->capacity) {
  57. kqueue_ctx_resize(kqueue_ctx, kqueue_ctx->capacity*2);
  58. }
  59. memset(kqueue_ctx->changes+idx, 0, sizeof(struct kevent));
  60. kqueue_ctx->changes[idx].ident = event->fd;
  61. }
  62. assert(kqueue_ctx->changes[idx].ident == event->fd);
  63. if (type & READ_EVENT) {
  64. kqueue_ctx->changes[idx].filter = EVFILT_READ;
  65. }
  66. else if (type & WRITE_EVENT) {
  67. kqueue_ctx->changes[idx].filter = EVFILT_WRITE;
  68. }
  69. kqueue_ctx->changes[idx].flags = EV_ADD|EV_ENABLE;
  70. struct timespec ts;
  71. ts.tv_sec = 0;
  72. ts.tv_nsec = 0;
  73. kevent(kqueue_ctx->kqfd, kqueue_ctx->changes, kqueue_ctx->nchanges, NULL, 0, &ts);
  74. return 0;
  75. }
  76. int _add_event(hevent_t* event, int type) {
  77. if (type & READ_EVENT) {
  78. __add_event(event, READ_EVENT);
  79. }
  80. if (type & WRITE_EVENT) {
  81. __add_event(event, WRITE_EVENT);
  82. }
  83. return 0;
  84. }
  85. static int __del_event(hevent_t* event, int type) {
  86. hloop_t* loop = event->loop;
  87. kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)loop->event_ctx;
  88. if (kqueue_ctx == NULL) return 0;
  89. int idx = event->event_index[EVENT_INDEX(type)];
  90. if (idx < 0) return 0;
  91. assert(kqueue_ctx->changes[idx].ident == event->fd);
  92. kqueue_ctx->changes[idx].flags = EV_DELETE;
  93. event->event_index[EVENT_INDEX(type)] = -1;
  94. int lastidx = kqueue_ctx->nchanges - 1;
  95. if (idx < lastidx) {
  96. // swap
  97. struct kevent tmp;
  98. tmp = kqueue_ctx->changes[idx];
  99. kqueue_ctx->changes[idx] = kqueue_ctx->changes[lastidx];
  100. kqueue_ctx->changes[lastidx] = tmp;
  101. auto iter = loop->events.find(kqueue_ctx->changes[idx].ident);
  102. if (iter != loop->events.end()) {
  103. iter->second->event_index[kqueue_ctx->changes[idx].filter == EVFILT_READ ? READ_INDEX : WRITE_INDEX] = idx;
  104. }
  105. }
  106. struct timespec ts;
  107. ts.tv_sec = 0;
  108. ts.tv_nsec = 0;
  109. kevent(kqueue_ctx->kqfd, kqueue_ctx->changes, kqueue_ctx->nchanges, NULL, 0, &ts);
  110. kqueue_ctx->nchanges--;
  111. return 0;
  112. }
  113. int _del_event(hevent_t* event, int type) {
  114. if (type & READ_EVENT) {
  115. __del_event(event, READ_EVENT);
  116. }
  117. if (type & WRITE_EVENT) {
  118. __del_event(event, WRITE_EVENT);
  119. }
  120. return 0;
  121. }
  122. int _handle_events(hloop_t* loop, int timeout) {
  123. kqueue_ctx_t* kqueue_ctx = (kqueue_ctx_t*)loop->event_ctx;
  124. if (kqueue_ctx == NULL) return 0;
  125. if (kqueue_ctx->nchanges == 0) return 0;
  126. struct timespec ts, *tp;
  127. if (timeout == INFINITE) {
  128. tp = NULL;
  129. }
  130. else {
  131. ts.tv_sec = timeout / 1000;
  132. ts.tv_nsec = (timeout % 1000) * 1000000;
  133. tp = &ts;
  134. }
  135. int nkqueue = kevent(kqueue_ctx->kqfd, kqueue_ctx->changes, kqueue_ctx->nchanges, kqueue_ctx->events, kqueue_ctx->nchanges, tp);
  136. if (nkqueue < 0) {
  137. perror("kevent");
  138. return nkqueue;
  139. }
  140. if (nkqueue == 0) return 0;
  141. int nevent = 0;
  142. for (int i = 0; i < nkqueue; ++i) {
  143. if (nevent == nkqueue) break;
  144. if (kqueue_ctx->events[i].flags & EV_ERROR) {
  145. continue;
  146. }
  147. ++nevent;
  148. int fd = kqueue_ctx->events[i].ident;
  149. int revent = kqueue_ctx->events[i].filter;
  150. auto iter = loop->events.find(fd);
  151. if (iter == loop->events.end()) {
  152. continue;
  153. }
  154. hevent_t* event = iter->second;
  155. if (revent == EVFILT_READ) {
  156. _on_read(event);
  157. }
  158. else if (revent == EVFILT_WRITE) {
  159. _on_write(event);
  160. }
  161. }
  162. return nevent;
  163. }
  164. #endif