mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 13:04:23 -04:00
new event_once interface; start of buffering interface for buffered events
svn:r93
This commit is contained in:
parent
1b974101b9
commit
ec2c1db47e
@ -21,7 +21,7 @@ EXTRA_DIST = acconfig.h err.c event.h evsignal.h event.3 kqueue.c \
|
|||||||
|
|
||||||
lib_LIBRARIES = libevent.a
|
lib_LIBRARIES = libevent.a
|
||||||
|
|
||||||
libevent_a_SOURCES = event.c
|
libevent_a_SOURCES = event.c buffer.c
|
||||||
libevent_a_LIBADD = @LIBOBJS@
|
libevent_a_LIBADD = @LIBOBJS@
|
||||||
|
|
||||||
include_HEADERS = event.h
|
include_HEADERS = event.h
|
||||||
|
165
buffer.c
Normal file
165
buffer.c
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002, 2003 Niels Provos <provos@citi.umich.edu>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
#endif
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#undef timeout_pending
|
||||||
|
#undef timeout_initialized
|
||||||
|
|
||||||
|
#include <event.h>
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
|
||||||
|
struct evbuffer *
|
||||||
|
evbuffer_new(void)
|
||||||
|
{
|
||||||
|
struct evbuffer *buffer;
|
||||||
|
|
||||||
|
if ((buffer = calloc(1, sizeof(struct evbuffer))) == NULL)
|
||||||
|
err(1, "%s: calloc", __func__);
|
||||||
|
|
||||||
|
return (buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
evbuffer_free(struct evbuffer *buffer)
|
||||||
|
{
|
||||||
|
if (buffer->buffer != NULL)
|
||||||
|
free(buffer->buffer);
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
|
||||||
|
{
|
||||||
|
evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
|
||||||
|
evbuffer_drain(inbuf, inbuf->off);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evbuffer_add_printf(struct evbuffer *buf, char *fmt, ...)
|
||||||
|
{
|
||||||
|
int res = -1;
|
||||||
|
char *msg;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
if (vasprintf(&msg, fmt, ap) == -1)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
res = strlen(msg);
|
||||||
|
evbuffer_add(buf, msg, res);
|
||||||
|
free(msg);
|
||||||
|
|
||||||
|
|
||||||
|
end:
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
evbuffer_add(struct evbuffer *buf, u_char *data, size_t datlen)
|
||||||
|
{
|
||||||
|
size_t need = buf->off + datlen;
|
||||||
|
|
||||||
|
if (buf->totallen < need) {
|
||||||
|
if ((buf->buffer = realloc(buf->buffer, need)) == NULL)
|
||||||
|
err(1, "%s: realloc", __func__);
|
||||||
|
buf->totallen = need;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf->buffer + buf->off, data, datlen);
|
||||||
|
buf->off += datlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
evbuffer_drain(struct evbuffer *buf, size_t len)
|
||||||
|
{
|
||||||
|
if (len >= buf->off) {
|
||||||
|
buf->off = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(buf->buffer, buf->buffer + len, buf->off - len);
|
||||||
|
buf->off -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evbuffer_read(struct evbuffer *buffer, int fd, int howmuch)
|
||||||
|
{
|
||||||
|
u_char inbuf[4096];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (howmuch < 0 || howmuch > sizeof(inbuf))
|
||||||
|
howmuch = sizeof(inbuf);
|
||||||
|
|
||||||
|
n = read(fd, inbuf, howmuch);
|
||||||
|
if (n == -1)
|
||||||
|
return (-1);
|
||||||
|
if (n == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
evbuffer_add(buffer, inbuf, n);
|
||||||
|
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evbuffer_write(struct evbuffer *buffer, int fd)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = write(fd, buffer->buffer, buffer->off);
|
||||||
|
if (n == -1)
|
||||||
|
return (-1);
|
||||||
|
if (n == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
evbuffer_drain(buffer, n);
|
||||||
|
|
||||||
|
return (n);
|
||||||
|
}
|
||||||
|
|
||||||
|
u_char *
|
||||||
|
evbuffer_find(struct evbuffer *buffer, u_char *what, size_t len)
|
||||||
|
{
|
||||||
|
size_t remain = buffer->off;
|
||||||
|
u_char *search = buffer->buffer;
|
||||||
|
u_char *p;
|
||||||
|
|
||||||
|
while ((p = memchr(search, *what, remain)) != NULL && remain >= len) {
|
||||||
|
if (memcmp(p, what, len) == 0)
|
||||||
|
return (p);
|
||||||
|
|
||||||
|
search = p + 1;
|
||||||
|
remain = buffer->off - (size_t)(search - buffer->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
@ -2,7 +2,7 @@ dnl configure.in for libevent
|
|||||||
dnl Dug Song <dugsong@monkey.org>
|
dnl Dug Song <dugsong@monkey.org>
|
||||||
AC_INIT(event.c)
|
AC_INIT(event.c)
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE(libevent,0.7b)
|
AM_INIT_AUTOMAKE(libevent,0.7c)
|
||||||
AM_CONFIG_HEADER(config.h)
|
AM_CONFIG_HEADER(config.h)
|
||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ AC_CHECK_LIB(socket, socket)
|
|||||||
|
|
||||||
dnl Checks for header files.
|
dnl Checks for header files.
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS(inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h)
|
AC_CHECK_HEADERS(stdarg.h inttypes.h stdint.h poll.h signal.h unistd.h sys/epoll.h sys/time.h sys/queue.h sys/event.h)
|
||||||
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
if test "x$ac_cv_header_sys_queue_h" = "xyes"; then
|
||||||
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
AC_MSG_CHECKING(for TAILQ_FOREACH in sys/queue.h)
|
||||||
AC_EGREP_CPP(yes,
|
AC_EGREP_CPP(yes,
|
||||||
|
17
event.3
17
event.3
@ -36,6 +36,7 @@
|
|||||||
.Nm event_set ,
|
.Nm event_set ,
|
||||||
.Nm event_add ,
|
.Nm event_add ,
|
||||||
.Nm event_del ,
|
.Nm event_del ,
|
||||||
|
.Nm event_once ,
|
||||||
.Nm event_pending ,
|
.Nm event_pending ,
|
||||||
.Nm event_initialized ,
|
.Nm event_initialized ,
|
||||||
.Nm evtimer_set ,
|
.Nm evtimer_set ,
|
||||||
@ -65,6 +66,8 @@
|
|||||||
.Ft int
|
.Ft int
|
||||||
.Fn "event_del" "struct event *ev"
|
.Fn "event_del" "struct event *ev"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
.Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv"
|
||||||
|
.Ft int
|
||||||
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
|
.Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn "event_initialized" "struct event *ev"
|
.Fn "event_initialized" "struct event *ev"
|
||||||
@ -234,6 +237,20 @@ will cancel the event in the argument
|
|||||||
If the event has already executed or has never been added
|
If the event has already executed or has never been added
|
||||||
the call will have no effect.
|
the call will have no effect.
|
||||||
.Pp
|
.Pp
|
||||||
|
The function
|
||||||
|
.Fn event_once
|
||||||
|
is similiar to
|
||||||
|
.Fn event_set .
|
||||||
|
However, it schedules a callback to be called exactly once and does not
|
||||||
|
require the caller to prepare an
|
||||||
|
.Fa event
|
||||||
|
structure.
|
||||||
|
This function supports
|
||||||
|
.Fa EV_TIMEOUT ,
|
||||||
|
.Fa EV_READ
|
||||||
|
and
|
||||||
|
.Fa EV_WRITE .
|
||||||
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn event_pending
|
.Fn event_pending
|
||||||
function can be used to check if the event specified by
|
function can be used to check if the event specified by
|
||||||
|
59
event.c
59
event.c
@ -273,6 +273,62 @@ event_loop(int flags)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sets up an event for processing once */
|
||||||
|
|
||||||
|
struct event_once {
|
||||||
|
struct event ev;
|
||||||
|
|
||||||
|
void (*cb)(int, short, void *);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* One-time callback, it deletes itself */
|
||||||
|
|
||||||
|
static void
|
||||||
|
event_once_cb(int fd, short events, void *arg)
|
||||||
|
{
|
||||||
|
struct event_once *eonce = arg;
|
||||||
|
|
||||||
|
(*eonce->cb)(fd, events, eonce->arg);
|
||||||
|
free(eonce);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedules an event once */
|
||||||
|
|
||||||
|
int
|
||||||
|
event_once(int fd, short events,
|
||||||
|
void (*callback)(int, short, void *), void *arg, struct timeval *tv)
|
||||||
|
{
|
||||||
|
struct event_once *eonce;
|
||||||
|
struct timeval etv;
|
||||||
|
|
||||||
|
if ((eonce = calloc(1, sizeof(struct event_once))) == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
if (events == EV_TIMEOUT) {
|
||||||
|
if (tv == NULL) {
|
||||||
|
timerclear(&etv);
|
||||||
|
tv = &etv;
|
||||||
|
}
|
||||||
|
|
||||||
|
eonce->cb = callback;
|
||||||
|
eonce->arg = arg;
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
/* Bad event combination */
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_add(&eonce->ev, tv);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
event_set(struct event *ev, int fd, short events,
|
event_set(struct event *ev, int fd, short events,
|
||||||
void (*callback)(int, short, void *), void *arg)
|
void (*callback)(int, short, void *), void *arg)
|
||||||
@ -445,6 +501,9 @@ timeout_next(struct timeval *tv)
|
|||||||
|
|
||||||
timersub(&ev->ev_timeout, &now, tv);
|
timersub(&ev->ev_timeout, &now, tv);
|
||||||
|
|
||||||
|
assert(tv->tv_sec >= 0);
|
||||||
|
assert(tv->tv_usec >= 0);
|
||||||
|
|
||||||
LOG_DBG((LOG_MISC, 60, "timeout_next: in %d seconds", tv->tv_sec));
|
LOG_DBG((LOG_MISC, 60, "timeout_next: in %d seconds", tv->tv_sec));
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
25
event.h
25
event.h
@ -1,5 +1,3 @@
|
|||||||
/* $OpenBSD: event.h,v 1.4 2002/07/12 18:50:48 provos Exp $ */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -153,6 +151,8 @@ void timeout_process(void);
|
|||||||
#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||||
|
|
||||||
void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
|
void event_set(struct event *, int, short, void (*)(int, short, void *), void *);
|
||||||
|
int event_once(int, short, void (*)(int, short, void *), void *, struct timeval *);
|
||||||
|
|
||||||
int event_add(struct event *, struct timeval *);
|
int event_add(struct event *, struct timeval *);
|
||||||
int event_del(struct event *);
|
int event_del(struct event *);
|
||||||
void event_active(struct event *, int, short);
|
void event_active(struct event *, int, short);
|
||||||
@ -165,6 +165,27 @@ int event_pending(struct event *, short, struct timeval *);
|
|||||||
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* These functions deal with buffering input and output */
|
||||||
|
|
||||||
|
struct evbuffer {
|
||||||
|
u_char *buffer;
|
||||||
|
|
||||||
|
size_t totallen;
|
||||||
|
size_t off;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EVBUFFER_LENGTH(x) (x)->off
|
||||||
|
|
||||||
|
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 *);
|
||||||
|
int evbuffer_add_printf(struct evbuffer *, char *fmt, ...);
|
||||||
|
void evbuffer_drain(struct evbuffer *, size_t);
|
||||||
|
int evbuffer_write(struct evbuffer *, int);
|
||||||
|
int evbuffer_read(struct evbuffer *, int, int);
|
||||||
|
u_char *evbuffer_find(struct evbuffer *, u_char *, size_t);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user