From d60d94e0c36cc45ab32773e3a7c47173a784e1f9 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Thu, 3 May 2012 01:43:56 +0200 Subject: [PATCH] Unix: implement uv_poll --- config-unix.mk | 1 + include/uv-private/uv-unix.h | 7 ++ src/unix/core.c | 9 +++ src/unix/internal.h | 4 ++ src/unix/poll.c | 130 +++++++++++++++++++++++++++++++++++ uv.gyp | 1 + 6 files changed, 152 insertions(+) create mode 100644 src/unix/poll.c diff --git a/config-unix.mk b/config-unix.mk index cdcf5eaf9..8d26fc445 100644 --- a/config-unix.mk +++ b/config-unix.mk @@ -37,6 +37,7 @@ OBJS += src/unix/fs.o OBJS += src/unix/idle.o OBJS += src/unix/loop.o OBJS += src/unix/pipe.o +OBJS += src/unix/poll.o OBJS += src/unix/prepare.o OBJS += src/unix/process.o OBJS += src/unix/stream.o diff --git a/include/uv-private/uv-unix.h b/include/uv-private/uv-unix.h index e190b8534..08b2d120a 100644 --- a/include/uv-private/uv-unix.h +++ b/include/uv-private/uv-unix.h @@ -45,6 +45,8 @@ typedef struct { typedef int uv_file; +typedef int uv_platform_socket_t; + #define UV_ONCE_INIT PTHREAD_ONCE_INIT typedef pthread_once_t uv_once_t; @@ -162,6 +164,11 @@ typedef void* uv_lib_t; const char* pipe_fname; /* strdup'ed */ +/* UV_POLL */ +#define UV_POLL_PRIVATE_FIELDS \ + ev_io io_watcher; + + /* UV_PREPARE */ \ #define UV_PREPARE_PRIVATE_FIELDS \ ev_prepare prepare_watcher; \ diff --git a/src/unix/core.c b/src/unix/core.c index 9602b6429..c5a7da5f5 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -107,6 +107,10 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { uv__fs_event_close((uv_fs_event_t*)handle); break; + case UV_POLL: + uv__poll_close((uv_poll_t*)handle); + break; + default: assert(0); } @@ -249,6 +253,9 @@ void uv__finish_close(uv_handle_t* handle) { case UV_FS_EVENT: break; + case UV_POLL: + break; + default: assert(0); break; @@ -285,6 +292,8 @@ int64_t uv_now(uv_loop_t* loop) { int uv_is_active(const uv_handle_t* handle) { switch (handle->type) { + case UV_POLL: + return uv__poll_active((const uv_poll_t*)handle); case UV_CHECK: return uv__check_active((const uv_check_t*)handle); case UV_IDLE: diff --git a/src/unix/internal.h b/src/unix/internal.h index d6c499bb5..724120d48 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -141,6 +141,10 @@ int uv__tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); void uv__pipe_accept(EV_P_ ev_io* watcher, int revents); +/* poll */ +void uv__poll_close(uv_poll_t* handle); +int uv__poll_active(const uv_poll_t* handle); + /* various */ int uv__check_active(const uv_check_t* handle); int uv__idle_active(const uv_idle_t* handle); diff --git a/src/unix/poll.c b/src/unix/poll.c new file mode 100644 index 000000000..ca2481136 --- /dev/null +++ b/src/unix/poll.c @@ -0,0 +1,130 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "internal.h" + +#include +#include +#include + + +static void uv__poll_io(EV_P_ ev_io* watcher, int ev_events) { + uv_poll_t* handle = watcher->data; + int events; + + if (ev_events & EV_ERROR) { + /* An error happened. Libev has implicitly stopped the watcher, but we */ + /* need to fix the refcount. */ + uv_ref(handle->loop); + uv__set_sys_error(handle->loop, EBADF); + handle->poll_cb(handle, -1, 0); + return; + } + + assert(ev_events & (EV_READ | EV_WRITE)); + assert((ev_events & ~(EV_READ | EV_WRITE)) == 0); + + events = 0; + if (ev_events & EV_READ) + events |= UV_READABLE; + if (ev_events & EV_WRITE) + events |= UV_WRITABLE; + + handle->poll_cb(handle, 0, events); +} + + +int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { + uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); + loop->counters.poll_init++; + + handle->fd = fd; + handle->poll_cb = NULL; + + ev_init(&handle->io_watcher, uv__poll_io); + handle->io_watcher.data = handle; + + return 0; +} + + +int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, + uv_platform_socket_t socket) { + return uv_poll_init(loop, handle, socket); +} + + +static void uv__poll_stop(uv_poll_t* handle) { + if (ev_is_active(&handle->io_watcher)) { + ev_io_stop(handle->loop->ev, &handle->io_watcher); + uv_ref(handle->loop); + } +} + + +int uv_poll_stop(uv_poll_t* handle) { + assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + uv__poll_stop(handle); + return 0; +} + + +int uv_poll_start(uv_poll_t* handle, int events, uv_poll_cb poll_cb) { + int ev_events; + int was_active; + + assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); + assert(!(handle->flags & (UV_CLOSING | UV_CLOSED))); + + if (events == 0) { + uv__poll_stop(handle); + return 0; + } + + ev_events = 0; + if (events & UV_READABLE) + ev_events |= EV_READ; + if (events & UV_WRITABLE) + ev_events |= EV_WRITE; + + was_active = ev_is_active(&handle->io_watcher); + + ev_io_set(&handle->io_watcher, handle->fd, ev_events); + ev_io_start(handle->loop->ev, &handle->io_watcher); + + if (!was_active) + uv_unref(handle->loop); + + handle->poll_cb = poll_cb; + + return 0; +} + + +void uv__poll_close(uv_poll_t* handle) { + uv__poll_stop(handle); +} + + +int uv__poll_active(const uv_poll_t* handle) { + return ev_is_active(&handle->io_watcher); +} diff --git a/uv.gyp b/uv.gyp index ba9128eb8..21a29e0c1 100644 --- a/uv.gyp +++ b/uv.gyp @@ -199,6 +199,7 @@ 'src/unix/internal.h', 'src/unix/loop.c', 'src/unix/pipe.c', + 'src/unix/poll.c', 'src/unix/prepare.c', 'src/unix/process.c', 'src/unix/stream.c',