这三个也是 event_base_loop()的flag参数
/** @name Loop flags
These flags control the behavior of event_base_loop().
*/
/**@{*/
/** Block until we have an active event, then exit once all active events
* have had their callbacks run. */
#define EVLOOP_ONCE 0x01
/** Do not block: see which events are ready now, run the callbacks
* of the highest-priority ones, then exit. */
#define EVLOOP_NONBLOCK 0x02
/** Do not exit the loop because we have no pending events. Instead, keep
* running until event_base_loopexit() or event_base_loopbreak() makes us
* stop.
*/
#define EVLOOP_NO_EXIT_ON_EMPTY 0x04
/**@}*/
-
EVLOOP_ONCE
(0x01):- 含义: 运行事件循环一次。即,阻塞直到有活动事件发生,然后在处理完所有活动事件的回调后退出循环。
- 行为: 当设置了这个标志时,事件循环将会一直阻塞,直到有一个或多个事件变为活动状态。一旦事件的回调函数被处理完,循环将会退出。适用于你希望事件循环处理完所有活动事件后立即退出的场景。
-
EVLOOP_NONBLOCK
(0x02):- 含义: 不进行阻塞检查。即,不等待新的事件发生,而是检查当前事件的状态,处理那些已经就绪的事件,然后退出循环。
- 行为: 当设置了这个标志时,事件循环不会阻塞。如果没有活动事件,事件循环将会快速退出。这适用于你希望在检查事件状态后立即退出的场景,例如周期性检查或非阻塞操作。
-
EVLOOP_NO_EXIT_ON_EMPTY
(0x04):- 含义: 即使没有待处理的事件,也不要退出循环。事件循环将会继续运行,直到调用
event_base_loopexit()
或event_base_loopbreak()
使其停止。 - 行为: 当设置了这个标志时,事件循环即使在没有活动事件的情况下也不会退出。它将继续运行,直到显式地要求它退出。这适用于需要长期运行的事件循环,直到收到特定的退出命令。
- 含义: 即使没有待处理的事件,也不要退出循环。事件循环将会继续运行,直到调用
/** Replacement for gettimeofday on platforms that lack it. */
#ifdef EVENT__HAVE_GETTIMEOFDAY
#define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz))
#else
struct timezone;
EVENT2_EXPORT_SYMBOL
int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
这段代码定义了一个函数evutil_gettimeofday
,它是用于获取当前时间的函数,用于替代一些平台中没有gettimeofday
函数的情况。
首先,代码中使用了#ifdef
和#define
来判断编译器是否支持gettimeofday
函数。如果支持,则直接使用gettimeofday
函数。如果不支持,则定义了一个名为evutil_gettimeofday
的函数,它接受两个参数:tv
和tz
,分别表示要设置的时间值和时区信息。
EV_TIMEOUT EV_READ EV_WRITE EV_SIGNAL EV_PERSIST EV_ET
宏定义 | 含义 |
---|---|
EV_SIGNAL | 信号事件 |
EV_READ | IO读事件 |
EV_WRITE | IO写事件 |
EV_PERSIST | 持续事件,事件触发一次后不会被删除,下次触发了还会继续调用回调函数处理 |
EV_TIMEOUT | 超时事件 |
/**
* @name event flags
* Flags to pass to event_new(), event_assign(), event_pending(), and
* anything else with an argument of the form "short events"
*/
/**@{*/
/** Indicates that a timeout has occurred. It's not necessary to pass
* this flag to event_for new()/event_assign() to get a timeout. */
#define EV_TIMEOUT 0x01
/** Wait for a socket or FD to become readable */
#define EV_READ 0x02
/** Wait for a socket or FD to become writeable */
#define EV_WRITE 0x04
/** Wait for a POSIX signal to be raised*/
#define EV_SIGNAL 0x08
/**
* Persistent event: won't get removed automatically when activated.
*
* When a persistent event with a timeout becomes activated, its timeout
* is reset to 0.
*/
#define EV_PERSIST 0x10
/** Select edge-triggered behavior, if supported by the backend. */
#define EV_ET 0x20
/**
* If this option is provided, then event_del() will not block in one thread
* while waiting for the event callback to complete in another thread.
* To use this option safely, you may need to use event_finalize() or
* event_free_finalize() in order to safely tear down an event in a
* multithreaded application. See those functions for more information.
**/
/**
*如果提供了这个选项,那么event_del()将不会在一个线程中阻塞
当在另一个线程中等待事件回调完成时。
*为了安全地使用这个选项,你可能需要使用event_finalize()或
event_free_finalize(),以便安全地删除事件
*多线程应用程序。有关更多信息,请参阅这些函数。
**/
#define EV_FINALIZE 0x40
/**
* Detects connection close events. You can use this to detect when a
* connection has been closed, without having to read all the pending data
* from a connection.
* Not all backends support EV_CLOSED. To detect or require it, use the
* feature flag EV_FEATURE_EARLY_CLOSE.
**/
#define EV_CLOSED 0x80
/**@}*/
/**
@name evtimer_* macros
Aliases for working with one-shot timer events
If you need EV_PERSIST timer use event_*() functions.
*/
/**@{*/
这个标志表示某超时时间流逝后事件成为激活的。构造事件的时候,EV_TIMEOUT标志是被忽略的:可以在添加事件的时候设置超时,也可以不设置。超时发生时,回调函数的what参数将带有这个标志
表示指定的文件描述符已经就绪,可以读取的时候,事件将成为激活的。
表示指定的文件描述符已经就绪,可以写入的时候,事件将成为激活的。
用于实现信号检测。见[[]]
表示事件是“持久的”,
默认情况下,每当未决事件成为激活的(因为fd已经准备好读取或者写入,或者因为超时),事件将在其回调被执行前成为非未决的。如果想让事件再次成为未决的,可以在回调函数中再次对其调用event_add()。
然而,如果设置了EV_PERSIST标志,事件就是持久的。这意味着即使其回调被激活,事件还是会保持为未决状态。如果想在回调中让事件成为非未决的,可以对其调用event_del()。
每次执行事件回调的时候,持久事件的超时值会被复位。因此,如果具有EV_READ|EV_PERSIST标志,以及5秒的超时值,则事件将在以下情况下成为激活的:
-
套接字已经准备好被读取的时候
-
从最后一次成为激活的开始,已经逝去5秒
表示如果底层的event_base后端支持边沿触发事件,则事件应该是边沿触发的。这个标志影响EV_READ和EV_WRITE的语义。
从2.0.1-alpha版本开始,可以有任意多个事件因为同样的条件而未决。比如说,可以有两个事件因为某个给定的fd已经就绪,可以读取而成为激活的。这种情况下,多个事件回调被执行的次序是不确定的。
这些标志定义在<event2/event.h>中。除了EV_ET在2.0.1-alpha版本中引入外,所有标志从1.0版本开始就存在了。
#define evtimer_assign(ev, b, cb, arg) \
event_assign((ev), (b), -1, 0, (cb), (arg))
#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#define evtimer_add(ev, tv) event_add((ev), (tv))
#define evtimer_del(ev) event_del(ev)
#define evtimer_pending(ev, tv) event_pending((ev), EV_TIMEOUT, (tv))
#define evtimer_initialized(ev) event_initialized(ev)
#define evsignal_add(ev, tv) event_add((ev), (tv))
#define evsignal_assign(ev, b, x, cb, arg) \
event_assign((ev), (b), (x), EV_SIGNAL|EV_PERSIST, cb, (arg))
#define evsignal_new(b, x, cb, arg) \
event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))
#define evsignal_del(ev) event_del(ev)
#define evsignal_pending(ev, tv) event_pending((ev), EV_SIGNAL, (tv))
#define evsignal_initialized(ev) event_initialized(ev)
/**
* A type wide enough to hold the output of "socket()" or "accept()". On
* Windows, this is an intptr_t; elsewhere, it is an int. */
#ifdef _WIN32
#define evutil_socket_t intptr_t
#else
#define evutil_socket_t int
#endif
These definitions are used when locking is not enabled. EVUTIL_NIL_STMT_
is typically a no-op or empty statement, meaning no locking is applied.
#define BEV_LOCK(b) EVUTIL_NIL_STMT_
#define BEV_UNLOCK(b) EVUTIL_NIL_STMT_
#define BEV_LOCK(b) do { \
struct bufferevent_private *locking = BEV_UPCAST(b); \
EVLOCK_LOCK(locking->lock, 0); \
} while (0)
#define BEV_UNLOCK(b) do { \
struct bufferevent_private *locking = BEV_UPCAST(b); \
EVLOCK_UNLOCK(locking->lock, 0); \
} while (0)
-
BEV_LOCK(b)
:b
是一个指向bufferevent
结构体的指针。BEV_UPCAST(b)
宏将b
转换为bufferevent_private
结构体的指针,并赋值给locking
。EVLOCK_LOCK(locking->lock, 0)
用于对locking
中的lock
进行加锁操作。这里的0
可能表示锁的某种标志或者选项,具体含义取决于EVLOCK_LOCK
的实现。
-
BEV_UNLOCK(b)
:b
也是一个指向bufferevent
结构体的指针。- 同样,
BEV_UPCAST(b)
将b
转换为bufferevent_private
结构体的指针,并赋值给locking
。 EVLOCK_UNLOCK(locking->lock, 0)
用于对locking
中的lock
进行解锁操作。这里的0
与加锁时的标志或选项相同。
/** 给定一个 bufferevent,返回其对应的 bufferevent_private。*/
/** Internal: Given a bufferevent, return its corresponding
* bufferevent_private. */
#define BEV_UPCAST(b) EVUTIL_UPCAST((b), struct bufferevent_private, bev)
/** Helper macro. If we know that a given pointer points to a field in a
structure, return a pointer to the structure itself. Used to implement
our half-baked C OO. Example:
struct subtype {
int x;
struct supertype common;
int y;
};
...
void fn(struct supertype *super) {
struct subtype *sub = EVUTIL_UPCAST(super, struct subtype, common);
...
}
*/
#define EVUTIL_UPCAST(ptr, type, field) \
((type *)(((char*)(ptr)) - evutil_offsetof(type, field)))
~~~