diff --git a/extra/exports b/extra/exports index 0ba25a20950ce6f13426af6cce4fc3921671d6f9..acbd2fae9b71c93f535c3575fab75072e638434d 100644 --- a/extra/exports +++ b/extra/exports @@ -174,14 +174,14 @@ coio_getaddrinfo coio_ares_getaddrinfo coio_ares_freeaddrinfo coio_ares_request_cancel -coio_wake_up_timer_alloc -coio_wake_up_timer_free -coio_wake_up_timer_set -coio_wake_up_timer_active -coio_wake_up_timer_reset -coio_wait_event_register -coio_wait_event_update -coio_wait_event_free +coio_timer_new +coio_timer_delete +coio_timer_start_delay +coio_timer_is_active +coio_timer_reset +coio_fd_watcher_new +coio_fd_watcher_track_events +coio_fd_watcher_delete coio_wait console_get_output_format console_set_output_format diff --git a/src/lib/core/coio.c b/src/lib/core/coio.c index 10cf1ee0bbba51c80fc327a2c430c11ef5be1446..73229e07a6babcdb5a5c714c0f8e3bedc6872d95 100644 --- a/src/lib/core/coio.c +++ b/src/lib/core/coio.c @@ -572,6 +572,12 @@ coio_wait(int fd, int events, double timeout) return wdata.revents & (EV_READ | EV_WRITE); } +/** Public type for async fd monitoring with coio */ +struct coio_fd_watcher { + /* File descriptr to track events */ + ev_io fd; +}; + static void coio_wait_event_cb(struct ev_loop *loop, ev_io *watcher, int revents) { @@ -583,40 +589,44 @@ coio_wait_event_cb(struct ev_loop *loop, ev_io *watcher, int revents) ev_io_stop(loop, watcher); } -API_EXPORT void * -coio_wait_event_register(int fd, int events) +API_EXPORT struct coio_fd_watcher * +coio_fd_watcher_new(int fd) { if (fiber_is_cancelled()) return NULL; - struct ev_io *io_watcher = xcalloc(1, sizeof(struct ev_io)); + struct coio_fd_watcher *watcher = + xcalloc(1, sizeof(struct coio_fd_watcher)); - ev_io_init(io_watcher, coio_wait_event_cb, fd, events); - io_watcher->data = fiber(); - - ev_io_start(loop(), io_watcher); + ev_io_init(&watcher->fd, coio_wait_event_cb, fd, EV_NONE); + watcher->fd.data = fiber(); - return io_watcher; + return watcher; } API_EXPORT void -coio_wait_event_update(void *io_watcher, int events) +coio_fd_watcher_track_events(struct coio_fd_watcher *watcher, int events) { - assert(io_watcher != NULL); - struct ev_io *watcher = io_watcher; + assert(watcher != NULL); + struct ev_io *io_watcher = &watcher->fd; - ev_io_stop(loop(), watcher); - ev_io_modify(watcher, events); + if (ev_is_active(io_watcher)) + ev_io_stop(loop(), io_watcher); + + ev_io_modify(io_watcher, events); ev_io_start(loop(), io_watcher); } API_EXPORT void -coio_wait_event_free(void *io_watcher) +coio_fd_watcher_delete(struct coio_fd_watcher *watcher) { - assert(io_watcher != NULL); + assert(watcher != NULL); + struct ev_io *io_watcher = &watcher->fd; + + if (ev_is_active(io_watcher)) + ev_io_stop(loop(), io_watcher); - ev_io_stop(loop(), io_watcher); - free(io_watcher); + free(watcher); } API_EXPORT int @@ -626,7 +636,7 @@ coio_close(int fd) return close(fd); } -/* async resolver request context */ +/** async resolver request context */ struct coio_ares_request { /* watcher for socket monitoring */ ev_io io_watcher; @@ -644,19 +654,26 @@ struct coio_ares_request { struct ares_options options; }; +/** Public type for using addrinfo request with coio */ +struct coio_addrinfo_request { + /* async resolver request context */ + struct coio_ares_request *ares_request; +}; + void -coio_ares_request_cancel(void *memory) +coio_ares_request_cancel(struct coio_addrinfo_request *coio_request) { - if (memory == NULL) + if (coio_request == NULL) return; - struct coio_ares_request *request = memory; + struct coio_ares_request *request = coio_request->ares_request; ev_io_stop(loop(), &request->io_watcher); ev_io_set(&request->io_watcher, -1, 0); ares_cancel(request->channel); ares_destroy(request->channel); + free(coio_request); } static void @@ -727,7 +744,7 @@ coio_ares_io_cb(struct ev_loop *loop, ev_io *watcher, int revents) } static struct coio_ares_request * -coio_ares_request_new(struct ares_addrinfo **destination, bool *error_occurred) +coio_ares_request_new(void) { struct coio_ares_request *request = xcalloc(1, sizeof(struct coio_ares_request)); @@ -736,8 +753,6 @@ coio_ares_request_new(struct ares_addrinfo **destination, bool *error_occurred) .options.sock_state_cb = coio_ares_sock_state_cb, .options.sock_state_cb_data = request, .io_watcher.data = request, - .error = error_occurred, - .result = destination, }; ev_init(&request->io_watcher, coio_ares_io_cb); @@ -753,8 +768,8 @@ coio_ares_request_new(struct ares_addrinfo **destination, bool *error_occurred) return request; } -void * -coio_ares_getaddrinfo(const char *host, struct ares_addrinfo **result, bool *error) +struct coio_addrinfo_request * +coio_ares_getaddrinfo(const char *host, struct ares_addrinfo **result) { /* * hints will not be used after ares_getaddrinfo() call, @@ -764,17 +779,18 @@ coio_ares_getaddrinfo(const char *host, struct ares_addrinfo **result, bool *err .ai_socktype = SOCK_STREAM, }; - struct coio_ares_request *request = coio_ares_request_new(result, - error); - if (request == NULL) { - *error = true; - return NULL; - } + struct coio_ares_request *request = coio_ares_request_new(); + assert(request != NULL); + request->result = result; ares_getaddrinfo(request->channel, host, NULL, &hints, coio_ares_addrinfo_cb, request); - return request; + struct coio_addrinfo_request *coio_request = + xcalloc(1, sizeof(struct coio_addrinfo_request)); + coio_request->ares_request = request; + + return coio_request; } void @@ -783,6 +799,12 @@ coio_ares_freeaddrinfo(struct ares_addrinfo *ptr) ares_freeaddrinfo(ptr); } +/** Public type for triggering fiber wakeup with coio */ +struct coio_timer { + /* Timer to wake up the currentt fiber after the installed delay */ + ev_timer wake_up_timer; +}; + static void coio_wake_up_timer_cb(struct ev_loop *loop, ev_timer *timer, int revents) { @@ -795,29 +817,30 @@ coio_wake_up_timer_cb(struct ev_loop *loop, ev_timer *timer, int revents) fiber_wakeup(((ev_timer *)timer)->data); } -void * -coio_wake_up_timer_alloc(void) +struct coio_timer * +coio_timer_new(void) { - return xcalloc(1, sizeof(ev_timer)); + return xcalloc(1, sizeof(struct coio_timer)); } void -coio_wake_up_timer_free(void *timer) +coio_timer_delete(struct coio_timer *timer) { assert(timer != NULL); + ev_timer *wakeup_timer = &timer->wake_up_timer; - if (ev_is_active(timer)) - ev_timer_stop(loop(), timer); + if (ev_is_active(wakeup_timer)) + ev_timer_stop(loop(), wakeup_timer); - free(timer); + free(wakeup_timer); } void -coio_wake_up_timer_set(void *timer, double delay) +coio_timer_start_delay(struct coio_timer *timer, double delay) { assert(timer != NULL); + ev_timer *wakeup_timer = &timer->wake_up_timer; - ev_timer *wakeup_timer = timer; wakeup_timer->data = fiber(); ev_timer_init(wakeup_timer, coio_wake_up_timer_cb, (ev_tstamp)delay, 0); @@ -825,19 +848,21 @@ coio_wake_up_timer_set(void *timer, double delay) } bool -coio_wake_up_timer_active(void *timer) +coio_timer_is_active(struct coio_timer *timer) { assert(timer != NULL); + ev_timer *wakeup_timer = &timer->wake_up_timer; - return ev_timer_remaining(loop(), timer) > 0.; + return ev_timer_remaining(loop(), wakeup_timer) > 0.; } void -coio_wake_up_timer_reset(void *timer) +coio_timer_reset(struct coio_timer *timer) { assert(timer != NULL); + ev_timer *wakeup_timer = &timer->wake_up_timer; - /* timer_active and ev_is_active has differrent semantics */ - if (coio_wake_up_timer_active(timer)) - ev_timer_stop(loop(), timer); + /* timer_is_active and ev_is_active has differrent semantics */ + if (coio_timer_is_active(timer)) + ev_timer_stop(loop(), wakeup_timer); } diff --git a/src/lib/core/coio.h b/src/lib/core/coio.h index 88d27261780cd8cd44a0d66f0bd4925e47880e58..ce8142e280d2a6a6293b928b53cb65db48ee2b26 100644 --- a/src/lib/core/coio.h +++ b/src/lib/core/coio.h @@ -198,42 +198,48 @@ coio_wait(int fd, int event, double timeout); API_EXPORT int coio_close(int fd); +/** pre-declaration */ +struct coio_fd_watcher; + /** - * Register the given file descriptor as event to wait until + * Create an ev_io event for the given file descriptor to wait until * it will be ready to allow read or(and) write operations. + * Not starts waiting, only constructs memory. * Not yields. * \param fd - non-blocking file descriptor. - * \param events - requested events to wait combination of - * TNT_IO_READ | TNT_IO_WRITE bit flags. - * \retval evt - pointer to the initialized io event memory, - * must be passed to coio_wait_event_free() when event no + * \retval pointer to the initialized coio_fd_watcher memory, + * must be passed to coio_fd_watcher_delete() when event no * longer needed. */ -API_EXPORT void * -coio_wait_event_register(int fd, int events); +API_EXPORT struct coio_fd_watcher * +coio_fd_watcher_new(int fd); /** - * Update the given event to wait until it will be ready to + * Push the given event to start waiting until it will be ready to * allow read or(and) write operations by applying bitwise * OR mask to existent expectations. + * The mask can include `COIO_READ` or `COIO_WRITE`. Pass 0 to unregister. * Not yields. - * \param io_watcher - pointer to the initialized io event - * memory allocated by coio_wait_event_register(). + * \param watcher - pointer to the initialized coio_fd_watcher + * allocated by coio_fd_watcher_new(). * \param events - requested events to wait combination of * TNT_IO_READ | TNT_IO_WRITE bit flags. */ API_EXPORT void -coio_wait_event_update(void *io_watcher, int events); +coio_fd_watcher_track_events(struct coio_fd_watcher *watcher, int events); /** - * Free memory previously allocated by coio_wait_event_alloc() + * Delete memory previously allocated by coio_fd_watcher_new() */ API_EXPORT void -coio_wait_event_free(void *evt); +coio_fd_watcher_delete(struct coio_fd_watcher *watcher); -/* pre-declaration */ +/** pre-declaration */ struct ares_addrinfo; +/** pre-declaration */ +struct coio_addrinfo_request; + /** * Initiate a host query by name and service and allocate context * to allow working with libev async io waiting. Not yields. @@ -245,9 +251,8 @@ struct ares_addrinfo; * freed by coio_ares_request_cancel() after use even if result didn't * return. */ -API_EXPORT void * -coio_ares_getaddrinfo(const char *host, struct ares_addrinfo **ares, - bool *error); +API_EXPORT struct coio_addrinfo_request * +coio_ares_getaddrinfo(const char *host, struct ares_addrinfo **ares); /** * Free memory of the asynchronous resolving result returned in ares @@ -261,21 +266,24 @@ coio_ares_freeaddrinfo(struct ares_addrinfo *ptr); * close file descriptors and free memory after coio_ares_getaddrinfo(). */ API_EXPORT void -coio_ares_request_cancel(void *memory); +coio_ares_request_cancel(struct coio_addrinfo_request *coio_request); + +/** pre-declaration */ +struct coio_timer; /** * Allocate enough zeroed memory for the requested wake up timer. * \retval timer - pointer to the initialized ev_timer memory. */ -API_EXPORT void * -coio_wake_up_timer_alloc(void); +API_EXPORT struct coio_timer * +coio_timer_new(void); /** - * Free memory previously allocated by coio_wake_up_timer_alloc - * \param timer - pointer to the allocated ev_timer memory. + * Free memory previously allocated by coio_timer_new + * \param timer - pointer to the allocated coio_timer memory. */ API_EXPORT void -coio_wake_up_timer_free(void *timer); +coio_timer_delete(struct coio_timer *timer); /** * Set and start a generic timeout which will wake the corresponding @@ -285,7 +293,7 @@ coio_wake_up_timer_free(void *timer); * negative values are supported). */ API_EXPORT void -coio_wake_up_timer_set(void *timer, double delay); +coio_timer_start_delay(struct coio_timer *timer, double delay); /** * Check if timer still not expired. @@ -294,14 +302,14 @@ coio_wake_up_timer_set(void *timer, double delay); * \retval false - otherwise */ API_EXPORT bool -coio_wake_up_timer_active(void *timer); +coio_timer_is_active(struct coio_timer *timer); /** - * Stop and reset a generic timeout installed by coio_wake_up_timer_set(). + * Stop and reset a generic timeout installed by coio_timer_set(). * \param timer - pointer to the allocated and initialized ev_timer memory. */ API_EXPORT void -coio_wake_up_timer_reset(void *timer); +coio_timer_reset(struct coio_timer *timer); /** \endcond public */