上篇阅读了ev.h里面一些监视器的声明,这篇阅读API声明。
ev.h 在对于API的声明部分,开头就是一个条件宏:
#if EV_PROTOTYPES
EV_API_DECL int ev_version_major (void) EV_THROW;
EV_API_DECL int ev_version_minor (void) EV_THROW;
EV_API_DECL unsigned int ev_supported_backends (void) EV_THROW;
EV_API_DECL unsigned int ev_recommended_backends (void) EV_THROW;
EV_API_DECL unsigned int ev_embeddable_backends (void) EV_THROW;
.
.
.
#endif
在EV_PROTOTYPES处有一条注释:
/* EV_PROTOTYPES can be used to switch of prototype declarations */
#ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1
#endif
这个宏可用于切换函数声明。
这里面都是一些重量级较高的函数,版本函数,后端函数等。
对于函数中的两个宏:
EV_API_DEC :: extern
EV_THROW :: throw()
对于这些API,只能深入.c源文件。
EV_API_DECL int ev_version_major (void) EV_THROW;
EV_API_DECL int ev_version_minor (void) EV_THROW;
这个函数是ev.h文件声明的第一个函数:
EV_API_DECL int ev_version_major (void) EV_THROW;//版本
在ev++.h文件中能找到对应的函数:
inline int version_major () throw ()
{
return ev_version_major ();
}
ev++.h和ev.h是相互包含的,从开头的宏定义就能看出。
ev.c对该函数的定义:
ecb_cold int
ev_version_major (void) EV_THROW
{
return EV_VERSION_MAJOR;
}
定义中出现了三个新宏,没办法,继续找。
对ecb_cold的定义:
#if ECB_GCC_VERSION(4,3)
#define ecb_artificial ecb_attribute ((__artificial__))
#define ecb_hot ecb_attribute ((__hot__))
#define ecb_cold ecb_attribute ((__cold__))
#else
#define ecb_artificial
#define ecb_hot
#define ecb_cold
#endif
是一个条件定义,不满足条件就删除(空白)。
转到 ECB_GCC_VERSION(4,3):
#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
#define ECB_GCC_VERSION(major,minor) 0
#else
#define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
#endif
这是第一次出现的地方。
可见它仍然是一个条件定义,满足就是0,那就对应以它为条件的else,不满足就有定义。
要看定义,就要找:_ GNUC _ 和 _ _GNUC_MINOR _ _
但是,这两个宏不在libev的源文件中,这两个宏是Linux GNU C预定义的宏。
这些宏都是以双下划线开始,以双下划线结束。
其中
_ GNUC _ :gcc的主版本号
_ GNUC_MINOR _ :次版本号
_ GNUC_PATCHLEVEL _:修正版本号。
这就可以理解上面的宏定义是为了满足GNU C的某个版本。
作者在版本区的宏定义前面加了几句注释:
/* many compilers define _GNUC_ to some versions but then only implement
* what their idiot authors think are the "more important" extensions,
* causing enormous grief in return for some better fake benchmark numbers.
* or so.
* we try to detect these and simply assume they are not gcc - if they have
* an issue with that they should have done it right in the first place.
*/
可见如果gcc满足某个版本,ecb_cold就定义为:ecb_attribute ((_ cold _))
#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
#define ecb_attribute(attrlist) __attribute__ (attrlist)
#else
#define ecb_attribute(attrlist)
#endif
这里_ attribute 是gnu c的一个机制, attribute _ 可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )。关键字__attribute__ 也可以对结构体(struct )或共用体(union )进行属性设置。大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。至于具体的每个关键字代表什么属性就不一一列举了。
可以看出,满足某个版本,就设置某些属性。
所有ecb_cold :: _ attribute ( cold _)
_attribute _((cold))
Hint that the marked function is “cold” and should be optimized for size, predicted as unlikely for branch prediction, and/or placed near other “cold” functions (so other functions can have improved cache locality).
函数前面使用这个扩展,表示该函数比较冷门,这样在分支预测机制里就不会对该函数进行预取,或说是将它和其他同样冷门(cold)的函数放到一块,这样它就很可能不会被放到缓存中来,而让更热门的指令放到缓存中。
所以是加在函数声明或定义的返回值之前的,对编译器起优化指引作用的参数。
那么距离解析完成就剩下return 后面的这个宏了:EV_VERSION_MAJOR
这个宏的定义在ev.h文件中。
#define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 24
ok,这个版本函数解析完成。
那么对应的函数:
EV_API_DECL int ev_version_minor (void) EV_THROW;
同理。