support event_loopexit(); idea from marius; and fix event_once()

svn:r94
This commit is contained in:
Niels Provos 2004-03-22 21:46:45 +00:00
parent ec2c1db47e
commit cd699abf44
3 changed files with 88 additions and 15 deletions

View File

@ -33,6 +33,7 @@
.Nm event_init ,
.Nm event_dispatch ,
.Nm event_loop ,
.Nm event_loopexit ,
.Nm event_set ,
.Nm event_add ,
.Nm event_del ,
@ -59,6 +60,8 @@
.Fn "event_dispatch"
.Ft int
.Fn "event_loop" "int flags"
.Ft int
.Fn "event_loopexit" "struct timeval *tv"
.Ft void
.Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg"
.Ft int
@ -146,6 +149,11 @@ events. The flags
and
.Va EVLOOP_NONBLOCK
are recognized.
The
.Nm event_loopexit
function allows the loop to be terminated after some amount of time
has passed.
The parameter indicates the time after which the loop should terminate.
.Pp
It is the responsibility of the caller to provide these functions with
pre-allocated event structures.

38
event.c
View File

@ -1,7 +1,5 @@
/* $OpenBSD: event.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -108,17 +106,19 @@ const struct eventop *eventops[] = {
const struct eventop *evsel;
void *evbase;
/* Handle signals */
/* Handle signals - This is a deprecated interface */
int (*event_sigcb)(void); /* Signal callback when gotsig is set */
int event_gotsig; /* Set in signal handler */
int event_gotterm; /* Set to terminate loop */
/* Prototypes */
void event_queue_insert(struct event *, int);
void event_queue_remove(struct event *, int);
int event_haveevents(void);
void event_process_active(void);
void timeout_insert(struct event *);
static void event_process_active(void);
static RB_HEAD(event_tree, event) timetree;
static struct event_list activequeue;
struct event_list signalqueue;
@ -180,7 +180,7 @@ event_haveevents(void)
TAILQ_FIRST(&signalqueue) || TAILQ_FIRST(&activequeue));
}
void
static void
event_process_active(void)
{
struct event *ev;
@ -201,12 +201,28 @@ event_process_active(void)
}
}
/*
* Wait continously for events. We exit only if no events are left.
*/
int
event_dispatch(void)
{
return (event_loop(0));
}
static void
event_loopexit_cb(int fd, short what, void *arg)
{
event_gotterm = 1;
}
int
event_loopexit(struct timeval *tv)
{
return (event_once(-1, EV_TIMEOUT, event_loopexit_cb, NULL, tv));
}
int
event_loop(int flags)
{
@ -219,6 +235,12 @@ event_loop(int flags)
done = 0;
while (!done) {
/* Terminate the loop if we have been asked to */
if (event_gotterm) {
event_gotterm = 0;
done = 1;
}
while (event_gotsig) {
event_gotsig = 0;
if (event_sigcb) {
@ -314,11 +336,11 @@ event_once(int fd, short events,
eonce->cb = callback;
eonce->arg = arg;
evtimer_set(&eonce->ev, event_once_cb, &eonce);
evtimer_set(&eonce->ev, event_once_cb, eonce);
} else if (events & (EV_READ|EV_WRITE)) {
events &= EV_READ|EV_WRITE;
event_set(&eonce->ev, fd, events, event_once_cb, &eonce);
event_set(&eonce->ev, fd, events, event_once_cb, eonce);
} else {
/* Bad event combination */
return (-1);

49
event.h
View File

@ -1,5 +1,5 @@
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
* Copyright (c) 2000-2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -126,6 +126,7 @@ int event_dispatch(void);
#define EVLOOP_ONCE 0x01
#define EVLOOP_NONBLOCK 0x02
int event_loop(int);
int event_loopexit(struct timeval *); /* Causes the loop to exit */
int timeout_next(struct timeval *);
void timeout_correct(struct timeval *);
@ -174,12 +175,54 @@ struct evbuffer {
size_t off;
};
#define EVBUFFER_READ 0x01
#define EVBUFFER_WRITE 0x02
#define EVBUFFER_EOF 0x10
#define EVBUFFER_ERROR 0x20
#define EVBUFFER_TIMEOUT 0x40
struct bufferevent;
typedef void (*evbuffercb)(struct bufferevent *, void *);
typedef void (*everrorcb)(struct bufferevent *, short what, void *);
struct bufferevent {
struct event ev_read;
struct event ev_write;
struct evbuffer *input;
struct evbuffer *output;
evbuffercb readcb;
evbuffercb writecb;
everrorcb errorcb;
void *cbarg;
int timeout_read; /* in seconds */
int timeout_write; /* in seconds */
short enabled; /* events that are currently enabled */
};
struct bufferevent *bufferevent_new(int fd,
evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);
int bufferevent_write(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
int bufferevent_enable(struct bufferevent *bufev, short event);
int bufferevent_disable(struct bufferevent *bufev, short event);
void bufferevent_settimeout(struct bufferevent *bufev,
int timeout_read, int timeout_write);
#define EVBUFFER_LENGTH(x) (x)->off
#define EVBUFFER_DATA(x) (x)->buffer
#define EVBUFFER_INPUT(x) (x)->input
#define EVBUFFER_OUTPUT(x) (x)->output
struct evbuffer *evbuffer_new(void);
void evbuffer_free(struct evbuffer *);
void evbuffer_add(struct evbuffer *, u_char *, size_t);
void evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
void evbuffer_free(struct evbuffer *);
int evbuffer_add(struct evbuffer *, u_char *, size_t);
int evbuffer_add_buffer(struct evbuffer *, struct evbuffer *);
int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
void evbuffer_drain(struct evbuffer *, size_t);
int evbuffer_write(struct evbuffer *, int);