diff --git a/src/ae.c b/src/ae.c index 742388d85..0fd5b4612 100644 --- a/src/ae.c +++ b/src/ae.c @@ -159,6 +159,10 @@ void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask) aeFileEvent *fe = &eventLoop->events[fd]; if (fe->mask == AE_NONE) return; + /* We want to always remove AE_BARRIER if set when AE_WRITABLE + * is removed. */ + if (mask & AE_WRITABLE) mask |= AE_BARRIER; + aeApiDelEvent(eventLoop, fd, mask); fe->mask = fe->mask & (~mask); if (fd == eventLoop->maxfd && fe->mask == AE_NONE) { @@ -421,8 +425,22 @@ int aeProcessEvents(aeEventLoop *eventLoop, int flags) fe->rfileProc(eventLoop,fd,fe->clientData,mask); } if (fe->mask & mask & AE_WRITABLE) { - if (!rfired || fe->wfileProc != fe->rfileProc) - fe->wfileProc(eventLoop,fd,fe->clientData,mask); + 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 (can_fire) fe->wfileProc(eventLoop,fd,fe->clientData,mask); } processed++; } diff --git a/src/ae.h b/src/ae.h index c49bfe233..df5174838 100644 --- a/src/ae.h +++ b/src/ae.h @@ -38,9 +38,14 @@ #define AE_OK 0 #define AE_ERR -1 -#define AE_NONE 0 -#define AE_READABLE 1 -#define AE_WRITABLE 2 +#define AE_NONE 0 /* No events registered. */ +#define AE_READABLE 1 /* Fire when descriptor is readable. */ +#define AE_WRITABLE 2 /* Fire when descriptor is writable. */ +#define AE_BARRIER 4 /* With WRITABLE, never fire the event if the + READABLE event already fired in the same event + loop iteration. Useful when you want to persist + things to disk before sending replies, and want + to do that in a group fashion. */ #define AE_FILE_EVENTS 1 #define AE_TIME_EVENTS 2 @@ -64,7 +69,7 @@ typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop); /* File event structure */ typedef struct aeFileEvent { - int mask; /* one of AE_(READABLE|WRITABLE) */ + int mask; /* one of AE_(READABLE|WRITABLE|BARRIER) */ aeFileProc *rfileProc; aeFileProc *wfileProc; void *clientData;