unix, win: store ares handles in a binary tree
Store the uv_ares_task_t handles in a red-black tree, not a linked list. Fixes #72.
This commit is contained in:
parent
c21184c103
commit
dfda5009c2
@ -1482,8 +1482,8 @@ struct uv_counters_s {
|
||||
|
||||
struct uv_loop_s {
|
||||
UV_LOOP_PRIVATE_FIELDS
|
||||
/* list used for ares task handles */
|
||||
uv_ares_task_t* uv_ares_handles_;
|
||||
/* RB_HEAD(uv__ares_tasks, uv_ares_task_t) */
|
||||
struct uv__ares_tasks { uv_ares_task_t* rbh_root; } uv_ares_handles_;
|
||||
/* Various thing for libeio. */
|
||||
uv_async_t uv_eio_want_poll_notifier;
|
||||
uv_async_t uv_eio_done_poll_notifier;
|
||||
|
||||
@ -62,7 +62,7 @@ static void uv__ares_io(struct ev_loop* ev, struct ev_io* watcher,
|
||||
|
||||
|
||||
/* Allocates and returns a new uv_ares_task_t */
|
||||
static uv_ares_task_t* uv__ares_task_create(int fd) {
|
||||
static uv_ares_task_t* uv__ares_task_create(uv_loop_t* loop, int fd) {
|
||||
uv_ares_task_t* h = malloc(sizeof(uv_ares_task_t));
|
||||
|
||||
if (h == NULL) {
|
||||
@ -70,6 +70,7 @@ static uv_ares_task_t* uv__ares_task_create(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h->loop = loop;
|
||||
h->sock = fd;
|
||||
|
||||
ev_io_init(&h->read_watcher, uv__ares_io, fd, EV_READ);
|
||||
@ -102,7 +103,7 @@ static void uv__ares_sockstate_cb(void* data, ares_socket_t sock,
|
||||
ev_timer_again(loop->ev, &loop->timer);
|
||||
}
|
||||
|
||||
h = uv__ares_task_create(sock);
|
||||
h = uv__ares_task_create(loop, sock);
|
||||
uv_add_ares_handle(loop, h);
|
||||
}
|
||||
|
||||
|
||||
@ -145,6 +145,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) {
|
||||
static int uv__loop_init(uv_loop_t* loop,
|
||||
struct ev_loop *(ev_loop_new)(unsigned int flags)) {
|
||||
memset(loop, 0, sizeof(*loop));
|
||||
RB_INIT(&loop->uv_ares_handles_);
|
||||
#if HAVE_KQUEUE
|
||||
loop->ev = ev_loop_new(EVBACKEND_KQUEUE);
|
||||
#else
|
||||
|
||||
@ -32,6 +32,10 @@
|
||||
#include "ares/inet_net_pton.h"
|
||||
#include "ares/inet_ntop.h"
|
||||
|
||||
#if !defined(__GNUC__) && !defined(__clang__)
|
||||
# define __attribute__(x)
|
||||
#endif
|
||||
|
||||
|
||||
size_t uv_strlcpy(char* dst, const char* src, size_t size) {
|
||||
size_t n;
|
||||
@ -180,57 +184,44 @@ int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) {
|
||||
}
|
||||
|
||||
|
||||
/* find matching ares handle in list */
|
||||
static int cmp_ares_tasks(const uv_ares_task_t* a, const uv_ares_task_t* b) {
|
||||
if (a->sock < b->sock) return -1;
|
||||
if (a->sock > b->sock) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
RB_GENERATE_INTERNAL(uv__ares_tasks, uv_ares_task_s, node, cmp_ares_tasks,
|
||||
inline static __attribute__((unused)))
|
||||
|
||||
|
||||
/* add ares handle to list */
|
||||
void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle) {
|
||||
handle->loop = loop;
|
||||
handle->ares_next = loop->uv_ares_handles_;
|
||||
handle->ares_prev = NULL;
|
||||
|
||||
if (loop->uv_ares_handles_) {
|
||||
loop->uv_ares_handles_->ares_prev = handle;
|
||||
}
|
||||
|
||||
loop->uv_ares_handles_ = handle;
|
||||
assert(loop == handle->loop);
|
||||
RB_INSERT(uv__ares_tasks, &loop->uv_ares_handles_, handle);
|
||||
}
|
||||
|
||||
|
||||
/* find matching ares handle in list */
|
||||
/* TODO: faster lookup */
|
||||
uv_ares_task_t* uv_find_ares_handle(uv_loop_t* loop, ares_socket_t sock) {
|
||||
uv_ares_task_t* handle = loop->uv_ares_handles_;
|
||||
|
||||
while (handle != NULL) {
|
||||
if (handle->sock == sock) {
|
||||
break;
|
||||
}
|
||||
handle = handle->ares_next;
|
||||
}
|
||||
|
||||
return handle;
|
||||
uv_ares_task_t handle;
|
||||
handle.sock = sock;
|
||||
return RB_FIND(uv__ares_tasks, &loop->uv_ares_handles_, &handle);
|
||||
}
|
||||
|
||||
|
||||
/* remove ares handle in list */
|
||||
void uv_remove_ares_handle(uv_ares_task_t* handle) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
|
||||
if (handle == loop->uv_ares_handles_) {
|
||||
loop->uv_ares_handles_ = handle->ares_next;
|
||||
}
|
||||
|
||||
if (handle->ares_next) {
|
||||
handle->ares_next->ares_prev = handle->ares_prev;
|
||||
}
|
||||
|
||||
if (handle->ares_prev) {
|
||||
handle->ares_prev->ares_next = handle->ares_next;
|
||||
}
|
||||
RB_REMOVE(uv__ares_tasks, &handle->loop->uv_ares_handles_, handle);
|
||||
}
|
||||
|
||||
|
||||
/* Returns 1 if the uv_ares_handles_ list is empty. 0 otherwise. */
|
||||
int uv_ares_handles_empty(uv_loop_t* loop) {
|
||||
return loop->uv_ares_handles_ ? 0 : 1;
|
||||
return RB_EMPTY(&loop->uv_ares_handles_);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
|
||||
if (handle->type != UV_TCP || addr.sin_family != AF_INET) {
|
||||
uv__set_artificial_error(handle->loop, UV_EFAULT);
|
||||
@ -240,6 +231,7 @@ int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) {
|
||||
return uv__tcp_bind(handle, addr);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
|
||||
if (handle->type != UV_TCP || addr.sin6_family != AF_INET6) {
|
||||
uv__set_artificial_error(handle->loop, UV_EFAULT);
|
||||
@ -249,6 +241,7 @@ int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) {
|
||||
return uv__tcp_bind6(handle, addr);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr,
|
||||
unsigned int flags) {
|
||||
if (handle->type != UV_UDP || addr.sin_family != AF_INET) {
|
||||
@ -259,6 +252,7 @@ int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr,
|
||||
return uv__udp_bind(handle, addr, flags);
|
||||
}
|
||||
|
||||
|
||||
int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr,
|
||||
unsigned int flags) {
|
||||
if (handle->type != UV_UDP || addr.sin6_family != AF_INET6) {
|
||||
@ -269,6 +263,7 @@ int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr,
|
||||
return uv__udp_bind6(handle, addr, flags);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_connect(uv_connect_t* req,
|
||||
uv_tcp_t* handle,
|
||||
struct sockaddr_in address,
|
||||
@ -281,6 +276,7 @@ int uv_tcp_connect(uv_connect_t* req,
|
||||
return uv__tcp_connect(req, handle, address, cb);
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_connect6(uv_connect_t* req,
|
||||
uv_tcp_t* handle,
|
||||
struct sockaddr_in6 address,
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#define UV_COMMON_H_
|
||||
|
||||
#include "uv.h"
|
||||
#include "tree.h"
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
@ -35,8 +36,7 @@
|
||||
struct uv_ares_task_s {
|
||||
UV_HANDLE_FIELDS
|
||||
UV_ARES_TASK_PRIVATE_FIELDS
|
||||
uv_ares_task_t* ares_prev;
|
||||
uv_ares_task_t* ares_next;
|
||||
RB_ENTRY(uv_ares_task_s) node;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -159,6 +159,7 @@ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read,
|
||||
}
|
||||
uv_handle_ares->type = UV_ARES_TASK;
|
||||
uv_handle_ares->close_cb = NULL;
|
||||
uv_handle_ares->loop = loop;
|
||||
uv_handle_ares->data = loop;
|
||||
uv_handle_ares->sock = sock;
|
||||
uv_handle_ares->h_wait = NULL;
|
||||
|
||||
@ -59,7 +59,6 @@ static void uv_init(void) {
|
||||
|
||||
|
||||
static void uv_loop_init(uv_loop_t* loop) {
|
||||
loop->uv_ares_handles_ = NULL;
|
||||
/* Create an I/O completion port */
|
||||
loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
|
||||
if (loop->iocp == NULL) {
|
||||
@ -75,6 +74,7 @@ static void uv_loop_init(uv_loop_t* loop) {
|
||||
loop->endgame_handles = NULL;
|
||||
|
||||
RB_INIT(&loop->timers);
|
||||
RB_INIT(&loop->uv_ares_handles_);
|
||||
|
||||
loop->check_handles = NULL;
|
||||
loop->prepare_handles = NULL;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user