Permalink
Browse files

refine the algo

git-svn-id: http://svn.coderepos.org/share/lang/c/picoev/trunk@35033 d0d07461-0603-4401-acd4-de1884942a52
  • Loading branch information...
1 parent 7e5efc5 commit df16b5e89e2ee99de684c4d7d36c9be2f4a1de0c kazuho committed Aug 25, 2009
Showing with 67 additions and 128 deletions.
  1. +7 −22 picoev.h
  2. +45 −74 picoev_epoll.c
  3. +14 −21 picoev_kqueue.c
  4. +1 −11 picoev_select.c
View
@@ -66,10 +66,13 @@ extern "C" {
#define PICOEV_READ 1
#define PICOEV_WRITE 2
#define PICOEV_TIMEOUT 4
+#define PICOEV_ADD 0x40000000
+#define PICOEV_DEL 0x20000000
+#define PICOEV_READWRITE (PICOEV_READ | PICOEV_WRITE)
#define PICOEV_TIMEOUT_IDX_UNUSED (UCHAR_MAX)
- typedef unsigned short picoev_loop_id_t;
+ typedef unsigned picoev_loop_id_t;
typedef struct picoev_loop_st picoev_loop;
@@ -84,7 +87,6 @@ extern "C" {
picoev_loop_id_t loop_id;
char events;
unsigned char timeout_idx; /* PICOEV_TIMEOUT_IDX_UNUSED if not used */
- int _backend; /* can be used by the backend (never ever touched by core) */
} picoev_fd;
struct picoev_loop_st {
@@ -119,12 +121,6 @@ extern "C" {
/* destroys a loop (defined by each backend) */
int picoev_destroy_loop(picoev_loop* loop);
- /* internal: initializes the backend */
- int picoev_init_backend(void);
-
- /* internal: destroys the backend */
- int picoev_deinit_backend(void);
-
/* internal: updates events to be watched (defined by each backend) */
int picoev_update_events_internal(picoev_loop* loop, int fd, int events);
@@ -165,22 +161,13 @@ extern "C" {
picoev.timeout_vec_of_vec_size
= PICOEV_RND_UP(picoev.timeout_vec_size, PICOEV_SIMD_BITS)
/ PICOEV_SHORT_BITS;
- if (picoev_init_backend() != 0) {
- free(picoev.fds);
- picoev.fds = NULL;
- picoev.max_fd = 0;
- return -1;
- }
return 0;
}
/* deinitializes picoev */
PICOEV_INLINE
int picoev_deinit(void) {
assert(PICOEV_IS_INITED);
- if (picoev_deinit_backend() != 0) {
- return -1;
- }
free(picoev._fds_free_addr);
picoev.fds = NULL;
picoev._fds_free_addr = NULL;
@@ -238,8 +225,7 @@ extern "C" {
target->loop_id = loop->loop_id;
target->events = 0;
target->timeout_idx = PICOEV_TIMEOUT_IDX_UNUSED;
- if (events != 0
- && picoev_update_events_internal(loop, fd, events) != 0) {
+ if (picoev_update_events_internal(loop, fd, events | PICOEV_ADD) != 0) {
target->loop_id = 0;
return -1;
}
@@ -253,8 +239,7 @@ extern "C" {
picoev_fd* target;
assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));
target = picoev.fds + fd;
- if (target->events != 0
- && picoev_update_events_internal(loop, fd, 0) != 0) {
+ if (picoev_update_events_internal(loop, fd, PICOEV_DEL) != 0) {
return -1;
}
picoev_set_timeout(loop, fd, 0);
@@ -275,7 +260,7 @@ extern "C" {
PICOEV_INLINE
int picoev_get_events(picoev_loop* loop __attribute__((unused)), int fd) {
assert(PICOEV_IS_INITED_AND_FD_IN_RANGE(fd));
- return picoev.fds[fd].events;
+ return picoev.fds[fd].events & PICOEV_READWRITE;
}
/* sets events to be watched for given desriptor */
View
@@ -32,54 +32,18 @@
#include <unistd.h>
#include "picoev.h"
+#ifndef PICOEV_EPOLL_DEFER_DELETES
+# define PICOEV_EPOLL_DEFER_DELETES 1
+#endif
+
typedef struct picoev_loop_epoll_st {
picoev_loop loop;
int epfd;
- int changed_fds; /* -1 if none */
struct epoll_event events[1024];
} picoev_loop_epoll;
-#define BACKEND_GET_NEXT_FD(backend) ((backend) >> 8)
-#define BACKEND_GET_OLD_EVENTS(backend) ((char)backend)
-#define BACKEND_BUILD(nextfd, oldevents) (((nextfd) << 8) | (oldevents))
-
picoev_globals picoev;
-__inline void picoev_call_epoll(picoev_loop_epoll* loop, int fd,
- picoev_fd* target)
-{
- if (loop->loop.loop_id != target->loop_id) {
- /* now used by another thread, disable */
- epoll_ctl(loop->epfd, EPOLL_CTL_DEL, fd, 0);
- } else if (target->_backend != -1) {
- /* apply changes even if the old and new flags are equivalent, if the
- socket was reopened, it might require re-assigning */
- int old_events = BACKEND_GET_OLD_EVENTS(target->_backend);
- if (old_events != 0 && target->events == 0) {
- epoll_ctl(loop->epfd, EPOLL_CTL_DEL, fd, 0);
- } else {
- struct epoll_event ev;
- int r;
- ev.events = ((target->events & PICOEV_READ) != 0 ? EPOLLIN : 0)
- | ((target->events & PICOEV_WRITE) != 0 ? EPOLLOUT : 0);
- ev.data.fd = fd;
- if (old_events != 0) {
- if (epoll_ctl(loop->epfd, EPOLL_CTL_MOD, fd, &ev) != 0) {
- assert(errno == ENOENT);
- r = epoll_ctl(loop->epfd, EPOLL_CTL_ADD, fd, &ev);
- assert(r == 0);
- }
- } else {
- if (epoll_ctl(loop->epfd, EPOLL_CTL_ADD, fd, &ev) != 0) {
- assert(errno == EEXIST);
- r = epoll_ctl(loop->epfd, EPOLL_CTL_MOD, fd, &ev);
- assert(r == 0);
- }
- }
- }
- }
-}
-
picoev_loop* picoev_create_loop(int max_timeout)
{
picoev_loop_epoll* loop;
@@ -100,7 +64,6 @@ picoev_loop* picoev_create_loop(int max_timeout)
free(loop);
return NULL;
}
- loop->changed_fds = -1;
return &loop->loop;
}
@@ -117,38 +80,54 @@ int picoev_destroy_loop(picoev_loop* _loop)
return 0;
}
-int picoev_init_backend()
-{
- int i;
-
- for (i = 0; i < picoev.max_fd; ++i) {
- picoev.fds[i]._backend = -1;
- }
-
- return 0;
-}
-
-int picoev_deinit_backend()
-{
- return 0;
-}
-
int picoev_update_events_internal(picoev_loop* _loop, int fd, int events)
{
picoev_loop_epoll* loop = (picoev_loop_epoll*)_loop;
picoev_fd* target = picoev.fds + fd;
+ struct epoll_event ev;
+ int epoll_ret;
assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd));
- if (target->events == events) {
+ if ((events & PICOEV_READWRITE) == target->events) {
return 0;
}
- /* update chain */
- if (target->_backend == -1) {
- target->_backend = BACKEND_BUILD(loop->changed_fds, target->events);
- loop->changed_fds = fd;
+ ev.events = ((events & PICOEV_READ) != 0 ? EPOLLIN : 0)
+ | ((events & PICOEV_WRITE) != 0 ? EPOLLOUT : 0);
+ ev.data.fd = fd;
+
+#define SET(op, check_error) do { \
+ epoll_ret = epoll_ctl(loop->epfd, op, fd, &ev); \
+ assert(! check_error || epoll_ret == 0); \
+ } while (0)
+
+#if PICOEV_EPOLL_DEFER_DELETES
+
+ if ((events & PICOEV_DEL) != 0) {
+ /* nothing to do */
+ } else if ((events & PICOEV_READWRITE) == 0) {
+ SET(EPOLL_CTL_DEL, 1);
+ } else {
+ SET(EPOLL_CTL_MOD, 0);
+ if (epoll_ret != 0) {
+ assert(errno == ENOENT);
+ SET(EPOLL_CTL_ADD, 1);
+ }
}
+
+#else
+
+ if ((events & PICOEV_READWRITE) == 0) {
+ SET(EPOLL_CTL_DEL, 1);
+ } else {
+ SET(target->events == 0 ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, 1);
+ }
+
+#endif
+
+#undef SET
+
target->events = events;
return 0;
@@ -159,17 +138,6 @@ int picoev_poll_once_internal(picoev_loop* _loop, int max_wait)
picoev_loop_epoll* loop = (picoev_loop_epoll*)_loop;
int i, nevents;
- if (loop->changed_fds != -1) {
- int fd = loop->changed_fds;
- do {
- picoev_fd* target = picoev.fds + fd;
- picoev_call_epoll(loop, fd, target);
- fd = BACKEND_GET_NEXT_FD(target->_backend);
- target->_backend = -1;
- } while (fd != -1);
- loop->changed_fds = -1;
- }
-
nevents = epoll_wait(loop->epfd, loop->events,
sizeof(loop->events) / sizeof(loop->events[0]),
max_wait * 1000);
@@ -186,7 +154,10 @@ int picoev_poll_once_internal(picoev_loop* _loop, int max_wait)
(*target->callback)(&loop->loop, event->data.fd, revents,
target->cb_arg);
} else {
- epoll_ctl(loop->epfd, EPOLL_CTL_DEL, event->data.fd, 0);
+#if PICOEV_EPOLL_DEFER_DELETES
+ event->events = 0;
+ epoll_ctl(loop->epfd, EPOLL_CTL_DEL, event->data.fd, event);
+#endif
}
}
return 0;
View
@@ -83,39 +83,32 @@ int picoev_destroy_loop(picoev_loop* _loop)
return 0;
}
-int picoev_init_backend()
-{
- return 0;
-}
-
-int picoev_deinit_backend()
-{
- return 0;
-}
-
int picoev_update_events_internal(picoev_loop* _loop, int fd, int events)
{
picoev_loop_kqueue* loop = (picoev_loop_kqueue*)_loop;
assert(PICOEV_FD_BELONGS_TO_LOOP(&loop->loop, fd));
-#define SET(ev, cmd) \
- EV_SET(loop->ev_queue + loop->ev_queue_off++, fd, \
- ((ev & PICOEV_READ) != 0 ? EVFILT_READ : 0) \
- | ((ev & PICOEV_WRITE) != 0 ? EVFILT_WRITE : 0), \
- cmd, 0, 0, NULL)
-
- if (picoev.fds[fd].events != 0) {
- SET(picoev.fds[fd].events, EV_ADD | EV_ENABLE);
+ if (events == target->events) {
+ return 0;
}
- if (events != 0) {
- SET(events, EV_ADD);
+
+#define SET(cmd) \
+ EV_SET(loop->ev_queue + loop->ev_queue_off++, fd, \
+ ((events & PICOEV_READ) != 0 ? EVFILT_READ : 0) \
+ | ((events & PICOEV_WRITE) != 0 ? EVFILT_WRITE : 0), \
+ (cmd), 0, 0, NULL)
+
+ if ((events & PICOEV_READWRITE) != 0) {
+ SET(EV_ADD | EV_ENABLE);
+ } else {
+ SET((evevnts & PICOEV_DEL) != 0 ? EV_DELETE : EV_DISABLE);
}
#undef SET
/* should call imediately if the user might be going to close the socket */
- if (events == 0 || loop->ev_queue_off + 2 >= EV_QUEUE_SZ) {
+ if ((events & PICOEV_DEL) == 0 || loop->ev_queue_off == EV_QUEUE_SZ) {
int r = kevent(loop->kq, loop->ev_queue, loop->ev_queue_off, NULL, 0, NULL);
assert(r == 0);
loop->ev_queue_off = 0;
View
@@ -55,19 +55,9 @@ int picoev_destroy_loop(picoev_loop* loop)
return 0;
}
-int picoev_init_backend()
-{
- return 0;
-}
-
-int picoev_deinit_backend()
-{
- return 0;
-}
-
int picoev_update_events_internal(picoev_loop* loop, int fd, int events)
{
- picoev.fds[fd].events = events;
+ picoev.fds[fd].events = events & PICOEV_READWRITE;
return 0;
}

0 comments on commit df16b5e

Please sign in to comment.