mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 13:04:23 -04:00
Merge branch '21_event_cleanup_v3'
This commit is contained in:
commit
0a396a02ba
@ -179,6 +179,15 @@ extern int event_debug_mode_on_;
|
|||||||
|
|
||||||
TAILQ_HEAD(evcallback_list, event_callback);
|
TAILQ_HEAD(evcallback_list, event_callback);
|
||||||
|
|
||||||
|
/* Sets up an event for processing once */
|
||||||
|
struct event_once {
|
||||||
|
LIST_ENTRY(event_once) next_once;
|
||||||
|
struct event ev;
|
||||||
|
|
||||||
|
void (*cb)(evutil_socket_t, short, void *);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
struct event_base {
|
struct event_base {
|
||||||
/** Function pointers and other data to describe this event_base's
|
/** Function pointers and other data to describe this event_base's
|
||||||
* backend. */
|
* backend. */
|
||||||
@ -310,6 +319,10 @@ struct event_base {
|
|||||||
/** Saved seed for weak random number generator. Some backends use
|
/** Saved seed for weak random number generator. Some backends use
|
||||||
* this to produce fairness among sockets. Protected by th_base_lock. */
|
* this to produce fairness among sockets. Protected by th_base_lock. */
|
||||||
struct evutil_weakrand_state weakrand_seed;
|
struct evutil_weakrand_state weakrand_seed;
|
||||||
|
|
||||||
|
/** List of event_onces that have not yet fired. */
|
||||||
|
LIST_HEAD(once_event_list, event_once) once_events;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct event_config_entry {
|
struct event_config_entry {
|
||||||
|
35
event.c
35
event.c
@ -805,6 +805,12 @@ event_base_free(struct event_base *base)
|
|||||||
event_debug(("%s: %d events were still set in base",
|
event_debug(("%s: %d events were still set in base",
|
||||||
__func__, n_deleted));
|
__func__, n_deleted));
|
||||||
|
|
||||||
|
while (LIST_FIRST(&base->once_events)) {
|
||||||
|
struct event_once *eonce = LIST_FIRST(&base->once_events);
|
||||||
|
LIST_REMOVE(eonce, next_once);
|
||||||
|
mm_free(eonce);
|
||||||
|
}
|
||||||
|
|
||||||
if (base->evsel != NULL && base->evsel->dealloc != NULL)
|
if (base->evsel != NULL && base->evsel->dealloc != NULL)
|
||||||
base->evsel->dealloc(base);
|
base->evsel->dealloc(base);
|
||||||
|
|
||||||
@ -1771,22 +1777,18 @@ done:
|
|||||||
return (retval);
|
return (retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets up an event for processing once */
|
|
||||||
struct event_once {
|
|
||||||
struct event ev;
|
|
||||||
|
|
||||||
void (*cb)(evutil_socket_t, short, void *);
|
|
||||||
void *arg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* One-time callback to implement event_base_once: invokes the user callback,
|
/* One-time callback to implement event_base_once: invokes the user callback,
|
||||||
* then deletes the allocated storage */
|
* then deletes the allocated storage */
|
||||||
static void
|
static void
|
||||||
event_once_cb(evutil_socket_t fd, short events, void *arg)
|
event_once_cb(evutil_socket_t fd, short events, void *arg)
|
||||||
{
|
{
|
||||||
struct event_once *eonce = arg;
|
struct event_once *eonce = arg;
|
||||||
|
struct event_base *base = eonce->ev.ev_base;
|
||||||
|
|
||||||
(*eonce->cb)(fd, events, eonce->arg);
|
(*eonce->cb)(fd, events, eonce->arg);
|
||||||
|
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||||
|
LIST_REMOVE(eonce, next_once);
|
||||||
|
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||||
event_debug_unassign(&eonce->ev);
|
event_debug_unassign(&eonce->ev);
|
||||||
mm_free(eonce);
|
mm_free(eonce);
|
||||||
}
|
}
|
||||||
@ -1808,6 +1810,7 @@ event_base_once(struct event_base *base, evutil_socket_t fd, short events,
|
|||||||
{
|
{
|
||||||
struct event_once *eonce;
|
struct event_once *eonce;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
int activate = 0;
|
||||||
|
|
||||||
/* We cannot support signals that just fire once, or persistent
|
/* We cannot support signals that just fire once, or persistent
|
||||||
* events. */
|
* events. */
|
||||||
@ -1828,8 +1831,7 @@ event_base_once(struct event_base *base, evutil_socket_t fd, short events,
|
|||||||
* don't put it on the timeout queue. This is one
|
* don't put it on the timeout queue. This is one
|
||||||
* idiom for scheduling a callback, so let's make
|
* idiom for scheduling a callback, so let's make
|
||||||
* it fast (and order-preserving). */
|
* it fast (and order-preserving). */
|
||||||
event_active(&eonce->ev, EV_TIMEOUT, 1);
|
activate = 1;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
} else if (events & (EV_READ|EV_WRITE)) {
|
} else if (events & (EV_READ|EV_WRITE)) {
|
||||||
events &= EV_READ|EV_WRITE;
|
events &= EV_READ|EV_WRITE;
|
||||||
@ -1841,11 +1843,20 @@ event_base_once(struct event_base *base, evutil_socket_t fd, short events,
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0) {
|
||||||
res = event_add(&eonce->ev, tv);
|
EVBASE_ACQUIRE_LOCK(base, th_base_lock);
|
||||||
|
if (activate)
|
||||||
|
event_active_nolock_(&eonce->ev, EV_TIMEOUT, 1);
|
||||||
|
else
|
||||||
|
res = event_add_nolock_(&eonce->ev, tv, 0);
|
||||||
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
mm_free(eonce);
|
mm_free(eonce);
|
||||||
return (res);
|
return (res);
|
||||||
|
} else {
|
||||||
|
LIST_INSERT_HEAD(&base->once_events, eonce, next_once);
|
||||||
|
}
|
||||||
|
EVBASE_RELEASE_LOCK(base, th_base_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -1005,9 +1005,11 @@ void event_free(struct event *);
|
|||||||
schedules a callback to be called exactly once, and does not require the
|
schedules a callback to be called exactly once, and does not require the
|
||||||
caller to prepare an event structure.
|
caller to prepare an event structure.
|
||||||
|
|
||||||
Note that in Libevent 2.0 and earlier, if the event is never triggered,
|
Note that in Libevent 2.0 and earlier, if the event is never triggered, the
|
||||||
the internal memory used to hold it will never be freed. This may be
|
internal memory used to hold it will never be freed. In Libevent 2.1,
|
||||||
fixed in a later version of Libevent.
|
the internal memory will get freed by event_base_free() if the event
|
||||||
|
is never triggered. The 'arg' value, however, will not get freed in either
|
||||||
|
case--you'll need to free that on your own if you want it to go away.
|
||||||
|
|
||||||
@param base an event_base
|
@param base an event_base
|
||||||
@param fd a file descriptor to monitor, or -1 for no fd.
|
@param fd a file descriptor to monitor, or -1 for no fd.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user