‘基类’与‘派生类’
基类在上文提到,是
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher
{
EV_WATCHER (ev_watcher)
} ev_watcher;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_list
{
EV_WATCHER_LIST (ev_watcher_list)
} ev_watcher_list;
/* base class, nothing to see here unless you subclass */
typedef struct ev_watcher_time
{
EV_WATCHER_TIME (ev_watcher_time)
} ev_watcher_time;
这并不是真正的类,只是抽象理解
派生类是:
ev_io
/* invoked when fd is either EV_READable or EV_WRITEable */
/* revent EV_READ, EV_WRITE */
typedef struct ev_io
{
EV_WATCHER_LIST (ev_io)
int fd; /* ro */
int events; /* ro */
} ev_io;
可见ev_io包含了重定义 EV_WATCHER_LIST (),所以就有了基类的属性,自带的属性是 int fd 和 int events,事件第一行的解释为:当fd发生读或写的时候,事件读或事件写触发。fd在linux里面比较形象是文件描述符,它就代表一个事件,当fd发生了读写事件的时候,就会调用相应的函数,并且会把这个事件加入到事件链表中。
ev_timer, ev_periodic
/* invoked after a specific time, repeatable (based on monotonic clock) */
/* revent EV_TIMEOUT */
typedef struct ev_timer
{
EV_WATCHER_TIME (ev_timer)
ev_tstamp repeat; /* rw */
} ev_timer;
/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */
/* revent EV_PERIODIC */
typedef struct ev_periodic
{
EV_WATCHER_TIME (ev_periodic)
ev_tstamp offset; /* rw */
ev_tstamp interval; /* rw */
ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */
} ev_periodic;
这两个事件监视器类似,一个是相对时间,一个是绝对时间。
ev_timer:在特定时间后调用,可重复(基于单调时钟),
ev_periodic:在某个特定的时间调用,可能会定期重复(基于UTC)
从继承上看,他们都继承EV_WATCHER_TIME父类,实现上来看,ev_periodic要更为复杂,从其他博客得知有一个区别:
ev_timer是相对时间,设置10s,那么就会在10s后触发。
ev_periodic是绝对时间,设置10s,如果修改系统时间延后一年,那它就会在一年10s后触发。
此外,这两个时间监视器并没有放在监视器的链表中。
ev_signal:
/* invoked when the given signal has been received */
/* revent EV_SIGNAL */
typedef struct ev_signal
{
EV_WATCHER_LIST (ev_signal)
int signum; /* ro */
} ev_signal;
当收到信号时,触发。
ev_child:
/* invoked when sigchld is received and waitpid indicates the given pid */
/* revent EV_CHILD */
/* does not support priorities */
typedef struct ev_child
{
EV_WATCHER_LIST (ev_child)
int flags; /* private */
int pid; /* ro */
int rpid; /* rw, holds the received pid */
int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */
} ev_child;
加入监视器链表中,结构体内保存一些线程信息。
ev_stat:
#if EV_STAT_ENABLE
/* st_nlink = 0 means missing file or other error */
# ifdef _WIN32
typedef struct _stati64 ev_statdata;
# else
typedef struct stat ev_statdata;
# endif
/* invoked each time the stat data changes for a given path */
/* revent EV_STAT */
typedef struct ev_stat
{
EV_WATCHER_LIST (ev_stat)
ev_timer timer; /* private */
ev_tstamp interval; /* ro */
const char *path; /* ro */
ev_statdata prev; /* ro */
ev_statdata attr; /* ro */
int wd; /* wd for inotify, fd for kqueue */
} ev_stat;
#endif
ev_stat是一个条件定义。
出现第一个宏是EV_STAT_ENABLE字面意思是支持文件系统?
这个宏出现在这些地方
转到宏定义:
#ifndef EV_STAT_ENABLE
# define EV_STAT_ENABLE EV_FEATURE_WATCHERS
#endif
可见EV_STAT_ENABLE 用 EV_FEATURE_WATCHERS宏替换,查看EV_FEATURE_WATCHERS:
#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16)
它是EV_FEATURES 和 16的 ‘与’值
查看EV_FEATURES:
#ifndef EV_FEATURES
# if defined __OPTIMIZE_SIZE__
# define EV_FEATURES 0x7c
# else
# define EV_FEATURES 0x7f
# endif
#endif
它实现了对32位系统文件和64位系统文件的支持。
结构体里还有一个ev_tstamp类型:
typedef double ev_tstamp;
ev_tstamp就是double类型
ev_idle:
#if EV_IDLE_ENABLE
/* invoked when the nothing else needs to be done, keeps the process from blocking */
/* revent EV_IDLE */
typedef struct ev_idle
{
EV_WATCHER (ev_idle)
} ev_idle;
#endif
当不需要执行其他操作时调用,防止进程阻塞
ev_prepare:
/* invoked for each run of the mainloop, just before the blocking call */
/* you can still change events in any way you like */
/* revent EV_PREPARE */
typedef struct ev_prepare
{
EV_WATCHER (ev_prepare)
} ev_prepare;
在阻塞之前调用
ev_check:
/* invoked for each run of the mainloop, just after the blocking call */
/* revent EV_CHECK */
typedef struct ev_check
{
EV_WATCHER (ev_check)
} ev_check;
在阻塞之后调用
ev_fork:
#if EV_FORK_ENABLE
/* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */
typedef struct ev_fork
{
EV_WATCHER (ev_fork)
} ev_fork;
#endif
条件事件,EV_FORK_ENABLE:
#ifndef EV_FORK_ENABLE
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif
fork进程的时候调用
ev_cleanup:
#if EV_CLEANUP_ENABLE
/* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */
typedef struct ev_cleanup
{
EV_WATCHER (ev_cleanup)
} ev_cleanup;
#endif
条件定义,EV_CLEANUP_ENABLE:
#ifndef EV_CLEANUP_ENABLE
# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS
#endif
在循环被破坏之前调用
ev_embed:
#if EV_EMBED_ENABLE
/* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */
typedef struct ev_embed
{
EV_WATCHER (ev_embed)
struct ev_loop *other; /* ro */
ev_io io; /* private */
ev_prepare prepare; /* private */
ev_check check; /* unused */
ev_timer timer; /* unused */
ev_periodic periodic; /* unused */
ev_idle idle; /* unused */
ev_fork fork; /* private */
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */
#endif
} ev_embed;
#endif
#ifndef EV_EMBED_ENABLE
# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS
#endif
将循环事件嵌入到另一个循环事件中
ev_async:
#if EV_ASYNC_ENABLE
/* invoked when somebody calls ev_async_send on the watcher */
/* revent EV_ASYNC */
typedef struct ev_async
{
EV_WATCHER (ev_async)
EV_ATOMIC_T sent; /* private */
} ev_async;
# define ev_async_pending(w) (+(w)->sent)
#endif
#ifndef EV_ASYNC_ENABLE
# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS
#endif
ev_any_watcher:
这是一个共同体声明,同一时刻一个共同体里面只能有一个变量,共同体里面的变量共用一个存储空间,存储空间取共同体里最大的变量所需要的空间。
/* the presence of this union forces similar struct layout */
union ev_any_watcher
{
struct ev_watcher w;
struct ev_watcher_list wl;
struct ev_io io;
struct ev_timer timer;
struct ev_periodic periodic;
struct ev_signal signal;
struct ev_child child;
#if EV_STAT_ENABLE
struct ev_stat stat;
#endif
#if EV_IDLE_ENABLE
struct ev_idle idle;
#endif
struct ev_prepare prepare;
struct ev_check check;
#if EV_FORK_ENABLE
struct ev_fork fork;
#endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE
struct ev_embed embed;
#endif
#if EV_ASYNC_ENABLE
struct ev_async async;
#endif
};
这里面罗列了所有的监视器.
到这里ev.h头文件里面关于监视器的声明就基本结束了,还剩下一堆的枚举和API的定义,其实对于一个库,掌握变量的定义和API函数的定义功能就可以掌握。
到后面还会阅读ev++.h,其实ev++.h和ev.h是相互包含的,文件的第二句便是。