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
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
*/
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.
;
}
+
+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)
{
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),