Remove the eventqueue list and the ev_next pointers.

Those pointers were once used to maintain a complete list of
inserted IO and signal events.  But such a list is now available by
walking over ev_io_map and ev_signal_map!  So all they did was
require extra pointer operations to maintain, and extra 8-16 bytes
of storage in each struct event.

To be cowardly and keep the option of going back to having this
redundancy, I'm wrapping the removed code in a set of ifdefs.

This is a first cut; it needs cleanups and stress-testing!!  In
particular, it just plain disables a couple of functions that could
probably be saved.

There seems to be a need for an evmap_{io,signal}_foreach() or something.
This commit is contained in:
Nick Mathewson 2012-01-27 16:35:04 -05:00
parent 7622d2659b
commit 604569bf3f
5 changed files with 62 additions and 8 deletions

View File

@ -232,8 +232,10 @@ struct event_base {
/** Mapping from signal numbers to enabled (added) events. */
struct event_signal_map sigmap;
#ifdef _EVENT_USE_EVENTLIST
/** All events that have been enabled (added) in this event_base */
struct event_list eventqueue;
#endif
/** Stored timeval; used to detect when time is running backwards. */
struct timeval event_tv;

21
event.c
View File

@ -590,7 +590,9 @@ event_base_new_with_config(const struct event_config *cfg)
gettime(base, &base->event_tv);
min_heap_ctor(&base->timeheap);
#ifdef _EVENT_USE_EVENTLIST
TAILQ_INIT(&base->eventqueue);
#endif
base->sig.ev_signal_pair[0] = -1;
base->sig.ev_signal_pair[1] = -1;
base->th_notify_fd[0] = -1;
@ -764,14 +766,8 @@ event_base_free(struct event_base *base)
}
/* Delete all non-internal events. */
for (ev = TAILQ_FIRST(&base->eventqueue); ev; ) {
struct event *next = TAILQ_NEXT(ev, ev_next);
if (!(ev->ev_flags & EVLIST_INTERNAL)) {
event_del(ev);
++n_deleted;
}
ev = next;
}
evmap_signal_delete_all(base);
evmap_io_delete_all(base);
while ((ev = min_heap_top(&base->timeheap)) != NULL) {
event_del(ev);
++n_deleted;
@ -821,7 +817,9 @@ event_base_free(struct event_base *base)
mm_free(base->activequeues);
#ifdef _EVENT_USE_EVENTLIST
EVUTIL_ASSERT(TAILQ_EMPTY(&base->eventqueue));
#endif
evmap_io_clear(&base->io);
evmap_signal_clear(&base->sigmap);
@ -2638,7 +2636,9 @@ event_queue_remove_inserted(struct event_base *base, struct event *ev)
}
DECR_EVENT_COUNT(base, ev);
ev->ev_flags &= ~EVLIST_INSERTED;
#ifdef _EVENT_USE_EVENTLIST
TAILQ_REMOVE(&base->eventqueue, ev, ev_next);
#endif
}
static void
event_queue_remove_active(struct event_base *base, struct event *ev)
@ -2743,7 +2743,9 @@ event_queue_insert_inserted(struct event_base *base, struct event *ev)
ev->ev_flags |= EVLIST_INSERTED;
#ifdef _EVENT_USE_EVENTLIST
TAILQ_INSERT_TAIL(&base->eventqueue, ev, ev_next);
#endif
}
static void
@ -3030,6 +3032,8 @@ evthread_make_base_notifiable(struct event_base *base)
void
event_base_dump_events(struct event_base *base, FILE *output)
{
#ifdef _EVENT_USE_EVENTLIST
/* re-enable XXXXXX */
struct event *e;
int i;
fprintf(output, "Inserted events:\n");
@ -3056,6 +3060,7 @@ event_base_dump_events(struct event_base *base, FILE *output)
(e->ev_res&EV_TIMEOUT)?" Timeout active":"");
}
}
#endif
}
void

View File

@ -90,6 +90,9 @@ void *evmap_io_get_fdinfo(struct event_io_map *ctx, evutil_socket_t fd);
int evmap_io_reinit(struct event_base *base);
int evmap_signal_reinit(struct event_base *base);
int evmap_io_delete_all(struct event_base *base);
int evmap_signal_delete_all(struct event_base *base);
void evmap_check_integrity(struct event_base *base);
#endif /* _EVMAP_H_ */

42
evmap.c
View File

@ -547,6 +547,45 @@ evmap_signal_reinit(struct event_base *base)
return res;
}
int
evmap_io_delete_all(struct event_base *base)
{
struct event_io_map *io = &base->io;
#ifdef EVMAP_USE_HT
struct event_map_entry **mapent;
HT_FOREACH(mapent, event_io_map, io) {
struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
#else
evutil_socket_t i;
for (i = 0; i < io->nentries; ++i) {
struct evmap_io *ctx = io->entries[i];
if (!ctx)
continue;
#endif
while (LIST_FIRST(&ctx->events))
event_del(LIST_FIRST(&ctx->events));
}
return 0;
}
int
evmap_signal_delete_all(struct event_base *base)
{
struct event_signal_map *sigmap = &base->sigmap;
int i;
for (i = 0; i < sigmap->nentries; ++i) {
struct evmap_signal *ctx = sigmap->entries[i];
if (!ctx)
continue;
while (!LIST_EMPTY(&ctx->events))
event_del(LIST_FIRST(&ctx->events));
}
return 0;
}
/** Per-fd structure for use with changelists. It keeps track, for each fd or
* signal using the changelist, of where its entry in the changelist is.
*/
@ -798,6 +837,8 @@ evmap_check_integrity(struct event_base *base)
int nsignals, ntimers, nio;
nsignals = ntimers = nio = 0;
#ifdef _EVENT_USE_EVENTLIST
/* XXXXX no-eventlist implementations can use some of this, surely? */
TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
@ -848,6 +889,7 @@ evmap_check_integrity(struct event_base *base)
}
}
#endif
EVUTIL_ASSERT(nio == 0);
EVUTIL_ASSERT(nsignals == 0);
/* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for

View File

@ -96,7 +96,9 @@ struct { \
struct event_base;
struct event {
TAILQ_ENTRY(event) ev_active_next;
#ifdef _EVENT_USE_EVENTLIST
TAILQ_ENTRY(event) ev_next;
#endif
/* for managing timeouts */
union {
TAILQ_ENTRY(event) ev_next_with_common_timeout;