mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-23 08:38:27 -05:00
54e4bbeabd
In general we do not want before/after sleep() callbacks to be called when we re-enter the event loop, since those calls are only designed in order to perform operations every main iteration of the event loop, and re-entering is often just a way to incrementally serve clietns with error messages or other auxiliary operations. However, if we call the callbacks, we are then forced to think at before/after sleep callbacks as re-entrant, which is much harder without any good need. However here there was also a clear bug: beforeSleep() was actually never called when re-entering the event loop. But the new afterSleep() callback was. This is broken and in this instance re-entering afterSleep() caused a modules GIL dead lock.
127 lines
4.7 KiB
C
127 lines
4.7 KiB
C
/* A simple event-driven programming library. Originally I wrote this code
|
|
* for the Jim's event-loop (Jim is a Tcl interpreter) but later translated
|
|
* it in form of a library for easy reuse.
|
|
*
|
|
* Copyright (c) 2006-2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Redis nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef __AE_H__
|
|
#define __AE_H__
|
|
|
|
#include <time.h>
|
|
|
|
#define AE_OK 0
|
|
#define AE_ERR -1
|
|
|
|
#define AE_NONE 0
|
|
#define AE_READABLE 1
|
|
#define AE_WRITABLE 2
|
|
|
|
#define AE_FILE_EVENTS 1
|
|
#define AE_TIME_EVENTS 2
|
|
#define AE_ALL_EVENTS (AE_FILE_EVENTS|AE_TIME_EVENTS)
|
|
#define AE_DONT_WAIT 4
|
|
#define AE_CALL_AFTER_SLEEP 8
|
|
|
|
#define AE_NOMORE -1
|
|
#define AE_DELETED_EVENT_ID -1
|
|
|
|
/* Macros */
|
|
#define AE_NOTUSED(V) ((void) V)
|
|
|
|
struct aeEventLoop;
|
|
|
|
/* Types and data structures */
|
|
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);
|
|
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
|
|
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);
|
|
typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop);
|
|
|
|
/* File event structure */
|
|
typedef struct aeFileEvent {
|
|
int mask; /* one of AE_(READABLE|WRITABLE) */
|
|
aeFileProc *rfileProc;
|
|
aeFileProc *wfileProc;
|
|
void *clientData;
|
|
} aeFileEvent;
|
|
|
|
/* Time event structure */
|
|
typedef struct aeTimeEvent {
|
|
long long id; /* time event identifier. */
|
|
long when_sec; /* seconds */
|
|
long when_ms; /* milliseconds */
|
|
aeTimeProc *timeProc;
|
|
aeEventFinalizerProc *finalizerProc;
|
|
void *clientData;
|
|
struct aeTimeEvent *next;
|
|
} aeTimeEvent;
|
|
|
|
/* A fired event */
|
|
typedef struct aeFiredEvent {
|
|
int fd;
|
|
int mask;
|
|
} aeFiredEvent;
|
|
|
|
/* State of an event based program */
|
|
typedef struct aeEventLoop {
|
|
int maxfd; /* highest file descriptor currently registered */
|
|
int setsize; /* max number of file descriptors tracked */
|
|
long long timeEventNextId;
|
|
time_t lastTime; /* Used to detect system clock skew */
|
|
aeFileEvent *events; /* Registered events */
|
|
aeFiredEvent *fired; /* Fired events */
|
|
aeTimeEvent *timeEventHead;
|
|
int stop;
|
|
void *apidata; /* This is used for polling API specific data */
|
|
aeBeforeSleepProc *beforesleep;
|
|
aeBeforeSleepProc *aftersleep;
|
|
} aeEventLoop;
|
|
|
|
/* Prototypes */
|
|
aeEventLoop *aeCreateEventLoop(int setsize);
|
|
void aeDeleteEventLoop(aeEventLoop *eventLoop);
|
|
void aeStop(aeEventLoop *eventLoop);
|
|
int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
|
|
aeFileProc *proc, void *clientData);
|
|
void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask);
|
|
int aeGetFileEvents(aeEventLoop *eventLoop, int fd);
|
|
long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds,
|
|
aeTimeProc *proc, void *clientData,
|
|
aeEventFinalizerProc *finalizerProc);
|
|
int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id);
|
|
int aeProcessEvents(aeEventLoop *eventLoop, int flags);
|
|
int aeWait(int fd, int mask, long long milliseconds);
|
|
void aeMain(aeEventLoop *eventLoop);
|
|
char *aeGetApiName(void);
|
|
void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep);
|
|
void aeSetAfterSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *aftersleep);
|
|
int aeGetSetSize(aeEventLoop *eventLoop);
|
|
int aeResizeSetSize(aeEventLoop *eventLoop, int setsize);
|
|
|
|
#endif
|