↑ 1 #include <stdio.h>
↑ 2 #include <string.h>
↑ 3 #include <sys/epoll.h>
↑ 4 #include <stdlib.h>
↑ 5 #include <unistd.h>
↑ 6 #include <time.h>
↑ 7 #include <errno.h>
↑ 8 #include <signal.h>
↑ 9 #include "rh_event.h"
↑ 10 #include "rh_bitset.h"
↑ 11 #include "log.h"
↑ 12
↑ 13
↑ 14 static rh_event_t * rh_event_signal [NSIG] = {0, };
↑ 15
↑ 16
↑ 17
↑ 18 static int rh_event_ep2rh (int ep_events);
↑ 19 static int rh_event_rh2ep (short rh_events);
↑ 20
↑ 21 static void rh_event_signal_handler(int sig)
↑ 22 {
↑ 23 if (NULL == rh_event_signal[sig])
↑ 24 return;
↑ 25
↑ 26 /*
↑ 27 *
↑ 28 * this is only the simple way.
↑ 29 *
↑ 30 * if there are more event bases then not the correct event is called.
↑ 31 *
↑ 32 * use the socketpair() stuff like in libevent.
↑ 33 *
↑ 34 */
↑ 35
↑ 36 rh_event_signal[sig]->cb (sig, RH_EVENT_SIGNAL,
↑ 37 rh_event_signal[sig]->arg);
↑ 38 }
↑ 39
↑ 40 int rh_event_base_init (struct rh_event_base *base, int timeout)
↑ 41 {
↑ 42 memset (base, 0, sizeof(*base));
↑ 43
↑ 44 TAILQ_INIT(&base->timeout_list);
↑ 45
↑ 46 base->fd = epoll_create (100);
↑ 47 if (base->fd == -1) {
↑ 48 return -1;
↑ 49 }
↑ 50
↑ 51 base->timeout = timeout;
↑ 52
↑ 53 return 0;
↑ 54 }
↑ 55
↑ 56 void rh_event_base_exit (struct rh_event_base *base)
↑ 57 {
↑ 58 ++base->exit;
↑ 59 }
↑ 60
↑ 61 void rh_event_base_destroy (struct rh_event_base *base)
↑ 62 {
↑ 63 if (base->fd > -1) {
↑ 64 close (base->fd);
↑ 65 base->fd = -1;
↑ 66 }
↑ 67
↑ 68 if (base->nodes) {
↑ 69 size_t i;
↑ 70
↑ 71 for (i=0; i<base->nodes_count; ++i) {
↑ 72 if (base->nodes[i]) {
↑ 73 free (base->nodes[i]);
↑ 74 base->nodes[i] = NULL;
↑ 75 }
↑ 76 }
↑ 77
↑ 78 free (base->nodes);
↑ 79 base->nodes = NULL;
↑ 80 }
↑ 81 }
↑ 82
↑ 83 int rh_event_dispatch (struct rh_event_base *base)
↑ 84 {
↑ 85 while (0 == base->exit) {
↑ 86 struct epoll_event ep_events[100];
↑ 87 int nep_events, i;
↑ 88 time_t time_current;
↑ 89
↑ 90 nep_events = epoll_wait(base->fd, ep_events, 100, 900);
↑ 91
↑ 92 #if 0
↑ 93 printf ("%s(%p): %d events\n", __FUNCTION__,
↑ 94 (void*)base, nep_events);
↑ 95 #endif
↑ 96
↑ 97 base->time = time_current = time(NULL);
↑ 98
↑ 99 if (-1 == nep_events && errno != EINTR)
↑100 return -1;
↑101
↑102 /* process events */
↑103 for (i=0; i < nep_events; ++i) {
↑104 struct rh_event_node *node;
↑105 short rh_events;
↑106 int fd;
↑107
↑108 rh_events = rh_event_ep2rh (ep_events[i].events);
↑109
↑110 fd = ep_events[i].data.fd;
↑111
↑112 node = base->nodes[fd];
↑113
↑114 if ( node->read &&
↑115 rh_events & (RH_EVENT_READ | RH_EVENT_ERROR) )
↑116 {
↑117 if (node->read->rh_events & RH_EVENT_TIMEOUT) {
↑118
↑119 if (node->read != TAILQ_LAST(
↑120 &base->timeout_list,
↑121 rh_event_list))
↑122 {
↑123 TAILQ_REMOVE(
↑124 &base->timeout_list,
↑125 node->read,
↑126 list);
↑127
↑128 TAILQ_INSERT_TAIL(
↑129 &base->timeout_list,
↑130 node->read,
↑131 list);
↑132 }
↑133
↑134 node->read->timeout_time = time_current;
↑135 }
↑136
↑137 node->read->cb(fd, rh_events,node->read->arg);
↑138
↑139 }
↑140
↑141 if ( node->write &&
↑142 rh_events & (RH_EVENT_WRITE| RH_EVENT_ERROR) )
↑143 {
↑144 if (node->write->rh_events & RH_EVENT_TIMEOUT) {
↑145 if (node->write != TAILQ_LAST(
↑146 &base->timeout_list,
↑147 rh_event_list))
↑148 {
↑149 TAILQ_REMOVE(
↑150 &base->timeout_list,
↑151 node->write,
↑152 list);
↑153
↑154 TAILQ_INSERT_TAIL(
↑155 &base->timeout_list,
↑156 node->write,
↑157 list);
↑158 }
↑159
↑160 node->write->timeout_time = time_current;
↑161 }
↑162
↑163 node->write->cb(fd, rh_events,node->write->arg);
↑164 }
↑165 } /* for (events) */
↑166
↑167 /* timeout */
↑168 for (;;) {
↑169 struct rh_event *event;
↑170
↑171 event = TAILQ_FIRST(&base->timeout_list);
↑172
↑173 if (NULL == event)
↑174 break;
↑175
↑176 if (time_current - event->timeout_time < base->timeout)
↑177 break;
↑178
↑179 DEBUGLOG("timeout. event(%p) fd(%d)",
↑180 (void*)event,
↑181 event->fd);
↑182
↑183 event->cb(event->fd, RH_EVENT_TIMEOUT, event->arg);
↑184 }
↑185 }
↑186
↑187 return 0;
↑188 }
↑189
↑190 static int rh_event_rh2ep (short rh_events)
↑191 {
↑192 int ep_events = 0;
↑193
↑194 if (rh_events & RH_EVENT_READ)
↑195 RH_BIT_SET(ep_events, EPOLLIN | EPOLLPRI);
↑196
↑197 if (rh_events & RH_EVENT_WRITE)
↑198 RH_BIT_SET(ep_events, EPOLLOUT);
↑199
↑200 if (rh_events & RH_EVENT_ERROR)
↑201 RH_BIT_SET(ep_events, EPOLLERR | EPOLLHUP);
↑202
↑203 if (rh_events & RH_EVENT_ET)
↑204 RH_BIT_SET(ep_events, EPOLLET);
↑205
↑206 return ep_events;
↑207 }
↑208
↑209 static int rh_event_ep2rh (int ep_events)
↑210 {
↑211 int rh_events = 0;
↑212
↑213 if (ep_events & (EPOLLIN | EPOLLPRI))
↑214 rh_events |= RH_EVENT_READ;
↑215
↑216 if (ep_events & EPOLLOUT)
↑217 rh_events |= RH_EVENT_WRITE;
↑218
↑219 if (ep_events & (EPOLLERR | EPOLLHUP))
↑220 rh_events |= RH_EVENT_ERROR;
↑221
↑222 return rh_events;
↑223 }
↑224
↑225 static int rh_event_node_resize (struct rh_event_base *base, size_t nodes_count)
↑226 {
↑227 struct rh_event_node **nodes;
↑228 size_t i;
↑229
↑230 if (nodes_count < base->nodes_count)
↑231 nodes_count = base->nodes_count + 1;
↑232
↑233 nodes_count = nodes_count + 128 - (nodes_count % 128);
↑234 #if 0
↑235 printf ("%s(): %u -> %u\n", __FUNCTION__,
↑236 base->nodes_count, nodes_count);
↑237 #endif
↑238 nodes = realloc (base->nodes, nodes_count * sizeof(nodes));
↑239
↑240 if (NULL == nodes)
↑241 return -1;
↑242
↑243 for (i=base->nodes_count; i<nodes_count; ++i) {
↑244 nodes[i] = calloc(1, sizeof(struct rh_event_node));
↑245 if (NULL == nodes[i]) {
↑246 /* nothing? */
↑247 }
↑248 }
↑249
↑250
↑251 base->nodes = nodes;
↑252 base->nodes_count = nodes_count;
↑253
↑254 return 0;
↑255 }
↑256
↑257
↑258 int rh_event_set (struct rh_event *event, struct rh_event_base *base,
↑259 int fd,
↑260 short events,
↑261 void (*cb)(int, short, void *),
↑262 void *arg)
↑263 {
↑264 if ( (events & RH_EVENT_SIGNAL) ) {
↑265 event->node = NULL;
↑266 } else {
↑267 if (fd < 0) {
↑268 errno = EINVAL;
↑269 return -1;
↑270 }
↑271
↑272 if ((1+fd) > base->nodes_count) {
↑273 if (0 != rh_event_node_resize(base, fd+1))
↑274 return -1;
↑275 }
↑276
↑277 event->node = base->nodes[fd];
↑278 event->node->ep_event.data.fd = fd;
↑279 }
↑280
↑281 event->fd = fd;
↑282 event->rh_events = events;
↑283 event->arg = arg;
↑284 event->cb = cb;
↑285 event->base = base;
↑286 event->timeout_time = time(NULL);
↑287
↑288 return 0;
↑289 }
↑290
↑291 int rh_event_signal_set (struct rh_event *event,
↑292 struct rh_event_base *base,
↑293 int sig,
↑294 void (*cb)(int, short, void *),
↑295 void *arg)
↑296 {
↑297 return rh_event_set (event, base, sig, RH_EVENT_SIGNAL, cb, arg);
↑298 }
↑299
↑300
↑301 int rh_event_del (struct rh_event *event)
↑302 {
↑303 struct rh_event_node *node;
↑304 int ep_events;
↑305 short rh_events;
↑306 int ep_op;
↑307
↑308 if (NULL == event || NULL == event->base)
↑309 return -1;
↑310
↑311 if (event->rh_events & RH_EVENT_SIGNAL) {
↑312 if (!RH_EVENT_ISSET(event))
↑313 return 0;
↑314
↑315 signal (event->fd, SIG_DFL);
↑316 rh_event_signal[event->fd] = NULL;
↑317
↑318 return 0;
↑319
↑320 }
↑321
↑322 if (event->fd < 0 || (1+event->fd) > event->base->nodes_count)
↑323 return -1;
↑324
↑325 #if 0
↑326 printf ("%s(%p) fd: %d\n", __FUNCTION__, (void*)event, event->fd);
↑327 #endif
↑328
↑329 node = event->node;
↑330
↑331 if (event->rh_events & RH_EVENT_READ)
↑332 node->read = NULL;
↑333
↑334 if (event->rh_events & RH_EVENT_WRITE)
↑335 node->write = NULL;
↑336
↑337 if (RH_BIT_ISSETFULL( event->rh_events,
↑338 RH_EVENT_DISPATCH|RH_EVENT_TIMEOUT))
↑339 {
↑340 TAILQ_REMOVE( &event->base->timeout_list,
↑341 event,
↑342 list);
↑343 }
↑344
↑345 event->rh_events &= ~RH_EVENT_DISPATCH;
↑346
↑347 rh_events = 0;
↑348
↑349 if (node->read && (node->read->rh_events & RH_EVENT_DISPATCH))
↑350 rh_events |= node->read->rh_events;
↑351
↑352 if (node->write && (node->write->rh_events & RH_EVENT_DISPATCH))
↑353 rh_events |= node->write->rh_events;
↑354
↑355 ep_events = rh_event_rh2ep (rh_events);
↑356
↑357 if (0 == ep_events)
↑358 ep_op = EPOLL_CTL_DEL;
↑359 else
↑360 ep_op = EPOLL_CTL_MOD;
↑361
↑362 node->ep_event.events = ep_events;
↑363
↑364 //printf ("del: fd: %d ep_events: %d\n", event->fd, ep_events);
↑365
↑366 return epoll_ctl(event->base->fd, ep_op, event->fd, &node->ep_event);
↑367 }
↑368
↑369 int rh_event_add (struct rh_event *event)
↑370 {
↑371 struct rh_event_node *node;
↑372 short rh_events;
↑373 int ep_op;
↑374
↑375 #if 0
↑376 printf ("%s(%p) fd: %d\n", __FUNCTION__, (void*)event, event->fd);
↑377 #endif
↑378
↑379 if (NULL == event || NULL == event->base)
↑380 return -1;
↑381
↑382 if (RH_EVENT_ISSET(event))
↑383 return 0;
↑384
↑385 if (event->rh_events & RH_EVENT_SIGNAL) {
↑386 if (SIG_ERR == signal (event->fd, rh_event_signal_handler))
↑387 return -1;
↑388
↑389 rh_event_signal[event->fd] = event;
↑390
↑391 event->rh_events |= RH_EVENT_DISPATCH;
↑392
↑393 return 0;
↑394 }
↑395
↑396 if (event->fd < 0 || (1+event->fd) > event->base->nodes_count)
↑397 return -1;
↑398
↑399
↑400 node = event->node;
↑401
↑402 event->rh_events |= RH_EVENT_DISPATCH;
↑403
↑404 if (event->rh_events & RH_EVENT_TIMEOUT) {
↑405 TAILQ_INSERT_TAIL( &event->base->timeout_list,
↑406 event,
↑407 list);
↑408 }
↑409
↑410 if (event->rh_events & RH_EVENT_READ)
↑411 node->read = event;
↑412
↑413 if (event->rh_events & RH_EVENT_WRITE)
↑414 node->write = event;
↑415
↑416 rh_events = 0;
↑417
↑418 if (node->read && (node->read->rh_events & RH_EVENT_DISPATCH))
↑419 rh_events |= node->read->rh_events;
↑420
↑421 if (node->write && (node->write->rh_events & RH_EVENT_DISPATCH))
↑422 rh_events |= node->write->rh_events;
↑423
↑424 if (0 == node->ep_event.events)
↑425 ep_op = EPOLL_CTL_ADD;
↑426 else
↑427 ep_op = EPOLL_CTL_MOD;
↑428
↑429 node->ep_event.events = rh_event_rh2ep (rh_events);
↑430
↑431 return epoll_ctl(event->base->fd, ep_op, event->fd, &node->ep_event);
↑432 }
syntax highlighted by Code2HTML, v. 0.9.1