summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-02-27 12:16:26 +0100
committerantirez <antirez@gmail.com>2018-02-27 13:06:42 +0100
commit956350ef8951c56878c593dfd775693059c44056 (patch)
tree1ad43da030b138dfe3d3e9ce373151ea70ca8d6f
parent75987431f008e0072a70e7d5c001c1724a7fb421 (diff)
downloadredis-956350ef8951c56878c593dfd775693059c44056.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++;
}
}