summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-02-27 12:16:26 +0100
committerantirez <antirez@gmail.com>2018-02-27 12:16:26 +0100
commitb48a10a19678f1232620e26101a29d8f3087c3b8 (patch)
tree87ce7d80598b7d9ab1394116280e40c6a86757c7
parentec6484d7309e658fb5490c23aac55e00f235e63b (diff)
downloadredis-fsync-safety.tar.gz
ae.c: insetad of not firing, on AE_BARRIER invert the sequence.fsync-safety
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++;
}
}