summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-02-27 12:16:26 +0100
committerantirez <antirez@gmail.com>2018-02-27 16:19:38 +0100
commit1e2f0d694046e1e681e0e3a45b7f91316de2b3a9 (patch)
tree3abcfb61551fdd5ddef80dad33e18b7522c9433c
parentb2e4aad9e2ad5d2971831d5e5a41e8916363e6c9 (diff)
downloadredis-1e2f0d694046e1e681e0e3a45b7f91316de2b3a9.tar.gz
ae.c: insetad of not firing, on AE_BARRIER invert the sequence.
AE_BARRIER was implemented like: - Fire the readable event. - Do not fire the writabel event if the readable fired. However this may lead to the writable event to never be called if the readable event is always fired. There is an alterantive, we can just invert the sequence of the calls in case AE_BARRIER is set. This commit does that.
-rw-r--r--src/ae.c60
1 files changed, 38 insertions, 22 deletions
diff --git a/src/ae.c b/src/ae.c
index 0fd5b4612..6ed366fe1 100644
--- a/src/ae.c
+++ b/src/ae.c
@@ -415,33 +415,49 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags)
aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
int mask = eventLoop->fired[j].mask;
int fd = eventLoop->fired[j].fd;
- int rfired = 0;
-
- /* note the fe->mask & mask & ... code: maybe an already processed
- * event removed an element that fired and we still didn't
- * processed, so we check if the event is still valid. */
- if (fe->mask & mask & AE_READABLE) {
- rfired = 1;
+ int fired = 0; /* Number of events fired for current fd. */
+
+ /* Normally we execute the readable event first, and the writable
+ * event laster. This is useful as sometimes we may be able
+ * to serve the reply of a query immediately after processing the
+ * query.
+ *
+ * However if AE_BARRIER is set in the mask, our application is
+ * asking us to do the reverse: never fire the writable event
+ * after the readable. In such a case, we invert the calls.
+ * This is useful when, for instance, we want to do things
+ * in the beforeSleep() hook, like fsynching a file to disk,
+ * before replying to a client. */
+ int invert = fe->mask & AE_BARRIER;
+
+ /* Note the "fe->mask & mask & ..." code: maybe an already
+ * processed event removed an element that fired and we still
+ * didn't processed, so we check if the event is still valid.
+ *
+ * Fire the readable event if the call sequence is not
+ * inverted. */
+ if (!invert && fe->mask & mask & AE_READABLE) {
fe->rfileProc(eventLoop,fd,fe->clientData,mask);
+ fired++;
}
+
+ /* Fire the writable event. */
if (fe->mask & mask & AE_WRITABLE) {
- int can_fire = 1;
- if (rfired) {
- /* The previous event fired? We do not want this to
- * fire again if:
- *
- * 1. The handler is the same as the READABLE event.
- * 2. If there AE_BARRIER is set, to signal that we
- * are never allowed to fire WRITABLE after READABLE
- * in the same iteration. */
- if (fe->wfileProc == fe->rfileProc ||
- fe->mask & AE_BARRIER)
- {
- can_fire = 0;
- }
+ if (!fired || fe->wfileProc != fe->rfileProc) {
+ fe->wfileProc(eventLoop,fd,fe->clientData,mask);
+ fired++;
+ }
+ }
+
+ /* If we have to invert the call, fire the readable event now
+ * after the writable one. */
+ if (invert && fe->mask & mask & AE_READABLE) {
+ if (!fired || fe->wfileProc != fe->rfileProc) {
+ fe->rfileProc(eventLoop,fd,fe->clientData,mask);
+ fired++;
}
- if (can_fire) fe->wfileProc(eventLoop,fd,fe->clientData,mask);
}
+
processed++;
}
}