mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-09 12:28:19 -04:00
Add an event_remove_timer() to remove timer on an event without deleting it
This commit is contained in:
parent
5a9a014189
commit
e3b2e0869e
@ -383,6 +383,7 @@ int evsig_restore_handler_(struct event_base *base, int evsignal);
|
||||
int event_add_nolock_(struct event *ev,
|
||||
const struct timeval *tv, int tv_is_absolute);
|
||||
int event_del_nolock_(struct event *ev);
|
||||
int event_remove_timer_nolock_(struct event *ev);
|
||||
|
||||
void event_active_nolock_(struct event *ev, int res, short count);
|
||||
int event_callback_activate_(struct event_base *, struct event_callback *);
|
||||
|
39
event.c
39
event.c
@ -2193,6 +2193,45 @@ evthread_notify_base(struct event_base *base)
|
||||
return base->th_notify_fn(base);
|
||||
}
|
||||
|
||||
/* Implementation function to remove a timeout on a currently pending event.
|
||||
*/
|
||||
int
|
||||
event_remove_timer_nolock_(struct event *ev)
|
||||
{
|
||||
struct event_base *base = ev->ev_base;
|
||||
|
||||
EVENT_BASE_ASSERT_LOCKED(base);
|
||||
event_debug_assert_is_setup_(ev);
|
||||
|
||||
event_debug(("event_remove_timer_nolock: event: %p", ev));
|
||||
|
||||
/* If it's not pending on a timeout, we don't need to do anything. */
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT) {
|
||||
event_queue_remove_timeout(base, ev);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
event_remove_timer(struct event *ev)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (EVUTIL_FAILURE_CHECK(!ev->ev_base)) {
|
||||
event_warnx("%s: event has no event_base set.", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
EVBASE_ACQUIRE_LOCK(ev->ev_base, th_base_lock);
|
||||
|
||||
res = event_remove_timer_nolock_(ev);
|
||||
|
||||
EVBASE_RELEASE_LOCK(ev->ev_base, th_base_lock);
|
||||
|
||||
return (res);
|
||||
}
|
||||
|
||||
/* Implementation function to add an event. Works just like event_add,
|
||||
* except: 1) it requires that we have the lock. 2) if tv_is_absolute is set,
|
||||
* we treat tv as an absolute time, not as an interval to add to the current
|
||||
|
@ -1037,8 +1037,7 @@ int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_
|
||||
in calls to event_assign() until it is no longer pending.
|
||||
|
||||
If the event in the ev argument already has a scheduled timeout, calling
|
||||
event_add() replaces the old timeout with the new one, or clears the old
|
||||
timeout if the timeout argument is NULL.
|
||||
event_add() replaces the old timeout with the new one if tv is non-NULL.
|
||||
|
||||
@param ev an event struct initialized via event_set()
|
||||
@param timeout the maximum amount of time to wait for the event, or NULL
|
||||
@ -1048,6 +1047,17 @@ int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_
|
||||
*/
|
||||
int event_add(struct event *ev, const struct timeval *timeout);
|
||||
|
||||
/**
|
||||
Remove a timer from a pending event without removing the event itself.
|
||||
|
||||
If the event has a scheduled timeout, this function unschedules it but
|
||||
leaves the event otherwise pending.
|
||||
|
||||
@param ev an event struct initialized via event_assign() or event_new()
|
||||
@return 0 on success, or -1 if an error occurrect.
|
||||
*/
|
||||
int event_remove_timer(struct event *ev);
|
||||
|
||||
/**
|
||||
Remove an event from the set of monitored events.
|
||||
|
||||
|
@ -1410,6 +1410,71 @@ end:
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
static void incr_arg_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
int *intptr = arg;
|
||||
(void) fd; (void) what;
|
||||
++*intptr;
|
||||
}
|
||||
static void remove_timers_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
struct event **ep = arg;
|
||||
(void) fd; (void) what;
|
||||
event_remove_timer(ep[0]);
|
||||
event_remove_timer(ep[1]);
|
||||
}
|
||||
static void send_a_byte_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
evutil_socket_t *sockp = arg;
|
||||
(void) fd; (void) what;
|
||||
write(*sockp, "A", 1);
|
||||
}
|
||||
static void read_not_timeout_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
int *intp = arg;
|
||||
(void) fd; (void) what;
|
||||
*intp |= what;
|
||||
}
|
||||
|
||||
static void
|
||||
test_event_remove_timeout(void *ptr)
|
||||
{
|
||||
struct basic_test_data *data = ptr;
|
||||
struct event_base *base = data->base;
|
||||
struct event *ev[4];
|
||||
int ev0_fired=0, ev1_fired=0;
|
||||
struct timeval ms25 = { 0, 25*1000 },
|
||||
ms75 = { 0, 75*1000 },
|
||||
ms125 = { 0, 125*1000 };
|
||||
|
||||
event_base_assert_ok_(base);
|
||||
|
||||
ev[0] = event_new(base, data->pair[0], EV_READ,
|
||||
read_not_timeout_cb, &ev0_fired);
|
||||
ev[1] = evtimer_new(base, incr_arg_cb, &ev1_fired);
|
||||
ev[2] = evtimer_new(base, remove_timers_cb, ev);
|
||||
ev[3] = evtimer_new(base, send_a_byte_cb, &data->pair[1]);
|
||||
tt_assert(base);
|
||||
event_add(ev[2], &ms25); /* remove timers */
|
||||
event_add(ev[0], &ms75); /* read */
|
||||
event_add(ev[1], &ms75); /* timer */
|
||||
event_add(ev[3], &ms125); /* timeout. */
|
||||
event_base_assert_ok_(base);
|
||||
|
||||
event_base_dispatch(base);
|
||||
|
||||
tt_int_op(ev1_fired, ==, 0);
|
||||
tt_int_op(ev0_fired, ==, EV_READ);
|
||||
|
||||
event_base_assert_ok_(base);
|
||||
end:
|
||||
event_free(ev[0]);
|
||||
event_free(ev[1]);
|
||||
event_free(ev[2]);
|
||||
event_free(ev[3]);
|
||||
}
|
||||
|
||||
static void
|
||||
test_event_base_new(void *ptr)
|
||||
{
|
||||
@ -2559,6 +2624,7 @@ struct testcase_t main_testcases[] = {
|
||||
BASIC(bad_assign, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
|
||||
BASIC(bad_reentrant, TT_FORK|TT_NEED_BASE|TT_NO_LOGS),
|
||||
BASIC(active_later, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
||||
BASIC(event_remove_timeout, TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR),
|
||||
|
||||
/* These are still using the old API */
|
||||
LEGACY(persistent_timeout, TT_FORK|TT_NEED_BASE),
|
||||
|
Loading…
x
Reference in New Issue
Block a user