Event.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "util/events/libuv/UvWrapper.h"
  16. #include "memory/Allocator.h"
  17. #include "util/events/libuv/EventBase_pvt.h"
  18. #include "util/events/Event.h"
  19. #include "util/Identity.h"
  20. #include <stddef.h>
  21. #include <stdint.h>
  22. struct Event_pvt
  23. {
  24. struct Event pub;
  25. void (* const callback)(void* callbackContext);
  26. void* const callbackContext;
  27. uv_poll_t handler;
  28. struct Allocator* alloc;
  29. Identity
  30. };
  31. static void handleEvent(uv_poll_t* handle, int status, int events)
  32. {
  33. struct Event_pvt* event =
  34. Identity_check((struct Event_pvt*) (((char*)handle) - offsetof(struct Event_pvt, handler)));
  35. if ((status == 0) && (events & UV_READABLE)) {
  36. event->callback(event->callbackContext);
  37. }
  38. }
  39. static void freeEvent2(uv_handle_t* handle)
  40. {
  41. Allocator_onFreeComplete((struct Allocator_OnFreeJob*)handle->data);
  42. }
  43. static int freeEvent(struct Allocator_OnFreeJob* job)
  44. {
  45. struct Event_pvt* event = Identity_check((struct Event_pvt*) job->userData);
  46. event->handler.data = job;
  47. uv_close((uv_handle_t*) &event->handler, freeEvent2);
  48. return Allocator_ONFREE_ASYNC;
  49. }
  50. struct Event* Event_socketRead(void (* const callback)(void* callbackContext),
  51. void* const callbackContext,
  52. int s,
  53. struct EventBase* eventBase,
  54. struct Allocator* allocator,
  55. struct Except* eh)
  56. {
  57. struct EventBase_pvt* base = EventBase_privatize(eventBase);
  58. struct Allocator* alloc = Allocator_child(allocator);
  59. struct Event_pvt* out = Allocator_clone(alloc, (&(struct Event_pvt) {
  60. .callback = callback,
  61. .callbackContext = callbackContext,
  62. .alloc = alloc
  63. }));
  64. Identity_set(out);
  65. if (uv_poll_init(base->loop, &out->handler, s) != 0) {
  66. Allocator_free(alloc);
  67. Except_throw(eh, "Failed to create event. errno [%s]",
  68. uv_strerror(uv_last_error(base->loop)));
  69. }
  70. if (uv_poll_start(&out->handler, UV_READABLE, handleEvent) == -1) {
  71. Allocator_free(alloc);
  72. Except_throw(eh, "Failed to register event. errno [%s]",
  73. uv_strerror(uv_last_error(base->loop)));
  74. }
  75. out->handler.data = out;
  76. Allocator_onFree(alloc, freeEvent, out);
  77. return &out->pub;
  78. }