Commit Diff


commit - c7ef47709b71c178743625c10feca9f7cf373b80
commit + cc44e26db4154e11a027442878e1e34bc521e58e
blob - 0a0da1ce783c7d63c80448fd571d7dff5200b3a0
blob + cfe557178e73374aed6b61e63f62cb4cfa113824
--- ev.c
+++ ev.c
@@ -221,50 +221,20 @@ ev_signal(int sig, void (*cb)(int, int, void *), void 
 	return 0;
 }
 
-static inline void
-bubbleup(size_t i)
-{
-	struct evtimer	 tmp;
-	size_t		 p;
-
-	for (;;) {
-		if (i == 0)
-			return;
-
-		p = (i - 1) / 2;
-		if (timercmp(&base->timers[p].tv, &base->timers[i].tv, <))
-		    	return;
-
-		/* swap */
-		memcpy(&tmp, &base->timers[p], sizeof(tmp));
-		memcpy(&base->timers[p], &base->timers[i], sizeof(tmp));
-		memcpy(&base->timers[i], &tmp, sizeof(tmp));
-		i = p;
-	}
-}
-
 unsigned int
 ev_timer(const struct timeval *tv, void (*cb)(int, int, void*), void *udata)
 {
 	struct evtimer	*evt;
 	void		*t;
-	size_t		 tot, newcap, n;
+	size_t		 newcap;
 	unsigned int	 nextid;
-	int		 use_reserve;
 
 	if (tv == NULL) {
 		errno = EINVAL;
 		return 0;
-	}
-
-	use_reserve = 0;
-	tot = base->ntimers;
-	if (base->reserve_from != 0) {
-		use_reserve = 1;
-		tot = base->reserve_till;
 	}
 
-	if (tot == base->timerscap) {
+	if (base->reserve_till == base->timerscap) {
 		newcap = base->timerscap + 8;
 		t = recallocarray(base->timers, base->timerscap, newcap,
 		    sizeof(*base->timers));
@@ -277,23 +247,13 @@ ev_timer(const struct timeval *tv, void (*cb)(int, int
 	if ((nextid = ++base->tid) == 0)
 		nextid = ++base->tid;
 
-	n = base->ntimers;
-	if (use_reserve)
-		n = base->reserve_till;
-
-	evt = &base->timers[n];
+	evt = &base->timers[base->reserve_till];
 	evt->id = nextid;
 	memcpy(&evt->tv, tv, sizeof(*tv));
 	evt->cb.cb = cb;
 	evt->cb.udata = udata;
 
-	if (use_reserve)
-		base->reserve_till++;
-	else {
-		bubbleup(base->ntimers);
-		base->ntimers++;
-	}
-
+	base->reserve_till++;
 	return (nextid);
 }
 
@@ -415,6 +375,38 @@ ev_del(int fd)
 	return 0;
 }
 
+static void
+timerheapify(void)
+{
+	size_t		 i, reserve, gap;
+
+	reserve = base->reserve_till - base->reserve_from;
+	if (reserve == 0)
+		return;
+
+	gap = base->reserve_from - base->ntimers;
+	if (gap != 0) {
+		memmove(&base->timers[base->ntimers],
+		    &base->timers[base->reserve_from],
+		    reserve * sizeof(*base->timers));
+		base->reserve_from -= gap;
+		base->reserve_till -= gap;
+	}
+
+	base->ntimers = base->reserve_till;
+
+	if (base->ntimers < 2)
+		return;
+
+	i = base->ntimers / 2 - 1;
+	for (;;) {
+		bubbledown(i);
+		if (i == 0)
+			break;
+		i--;
+	}
+}
+
 static inline int
 poll2ev(int ev)
 {
@@ -434,9 +426,13 @@ ev_loop(void)
 	struct timespec	 elapsed, beg, end, min, *wait;
 	struct timeval	 tv, sub;
 	int		 n;
-	size_t		 i, gap;
+	size_t		 i;
 
 	while (!ev_stop) {
+		timerheapify();
+		base->reserve_from = base->ntimers;
+		base->reserve_till = base->ntimers;
+
 		wait = NULL;
 		if (base->ntimers) {
 			TIMEVAL_TO_TIMESPEC(&base->timers[0].tv, &min);
@@ -458,9 +454,6 @@ ev_loop(void)
 
 		TIMESPEC_TO_TIMEVAL(&tv, &elapsed);
 
-		base->reserve_from = base->ntimers;
-		base->reserve_till = base->ntimers;
-
 		for (i = 0; i < base->ntimers && !ev_stop; /* nop */) {
 			timersub(&base->timers[i].tv, &tv, &sub);
 			if (sub.tv_sec <= 0) {
@@ -484,24 +477,6 @@ ev_loop(void)
 				    base->cbs[i].udata);
 			}
 		}
-
-		if (base->reserve_from == base->reserve_till)
-			continue;
-
-		/* integrate the new timers in the heap */
-		gap = base->reserve_from - base->ntimers;
-		if (gap != 0) {
-			memmove(&base->timers[base->ntimers],
-			    &base->timers[base->reserve_from],
-			    gap * sizeof(*base->timers));
-			base->reserve_from -= gap;
-			base->reserve_till -= gap;
-		}
-
-		for (i = base->ntimers; i < base->reserve_till; ++i) {
-			base->ntimers++;
-			bubbleup(i);
-		}
 	}
 
 	return 0;