/* vim: set expandtab ts=4 sw=4: */ /* * You may redistribute this program and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation, * either version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "util/events/libuv/UvWrapper.h" #include "memory/Allocator.h" #include "util/events/libuv/EventBase_pvt.h" #include "util/events/Event.h" #include "util/Identity.h" #include #include struct Event_pvt { struct Event pub; void (* const callback)(void* callbackContext); void* const callbackContext; uv_poll_t handler; struct Allocator* alloc; Identity }; static void handleEvent(uv_poll_t* handle, int status, int events) { struct Event_pvt* event = Identity_check((struct Event_pvt*) (((char*)handle) - offsetof(struct Event_pvt, handler))); if ((status == 0) && (events & UV_READABLE)) { event->callback(event->callbackContext); } } static void freeEvent2(uv_handle_t* handle) { Allocator_onFreeComplete((struct Allocator_OnFreeJob*)handle->data); } static int freeEvent(struct Allocator_OnFreeJob* job) { struct Event_pvt* event = Identity_check((struct Event_pvt*) job->userData); event->handler.data = job; uv_close((uv_handle_t*) &event->handler, freeEvent2); return Allocator_ONFREE_ASYNC; } struct Event* Event_socketRead(void (* const callback)(void* callbackContext), void* const callbackContext, int s, struct EventBase* eventBase, struct Allocator* allocator, struct Except* eh) { struct EventBase_pvt* base = EventBase_privatize(eventBase); struct Allocator* alloc = Allocator_child(allocator); struct Event_pvt* out = Allocator_clone(alloc, (&(struct Event_pvt) { .callback = callback, .callbackContext = callbackContext, .alloc = alloc })); Identity_set(out); if (uv_poll_init(base->loop, &out->handler, s) != 0) { Allocator_free(alloc); Except_throw(eh, "Failed to create event. errno [%s]", uv_strerror(uv_last_error(base->loop))); } if (uv_poll_start(&out->handler, UV_READABLE, handleEvent) == -1) { Allocator_free(alloc); Except_throw(eh, "Failed to register event. errno [%s]", uv_strerror(uv_last_error(base->loop))); } out->handler.data = out; Allocator_onFree(alloc, freeEvent, out); return &out->pub; }