现在的位置: 首页 > 综合 > 正文

Apache源码分析——APR(1) 原子操作

2013年08月27日 ⁄ 综合 ⁄ 共 1775字 ⁄ 字号 评论关闭
首先介绍几个宏

1.APR_DECLARE 此宏是了定义函数的方式,可以方便其他模块调用Apache中函数,实现导入导出函数的定义。

打开Apache中APR项目,首先看到的就是atomic目录,此目录下仅有一个文件apr_atomic.c。打开此文件,转到此文件头文件可以

看到函数的定义及说明。在文件说明中,可以了解到此文件定义了一些原子操作,具体是哪些原子操作,可以看后面的函数定义。

首个函数是初始化操作函数:

APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p);

此函数的注释中国说明,在一些平台下需要做一些初始化操作(其中的参数apr_pool_t *p要使用的内存池,后面再做分析)。

换句话说,在另一些平台是不需要什么初始化操作的。看该函数实现的代码:

APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
{
    return APR_SUCCESS;
}

直接返回了成功值,没有做任何操作。

下一个函数:

APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem);

则是从内村中读取一个32位的无符号整型数字,其实现也是相当的简单呐:

APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
{
    return *mem;
}

而后的

APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val);

此函数分离出来就是

APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
{
   InterlockedExchange(mem, val);
}

此函数就是调用了windows api函数InterlockedExchange来改变了指定内存的值。

虽然如此,此函数也是有所学问滴,看函数原面貌:

typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_fn)
    (apr_uint32_t volatile *, 
     apr_uint32_t);

APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
{
#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED)
    InterlockedExchange(mem, val);
#elif defined(__MINGW32__)
    InterlockedExchange((long*)mem, val);
#else
    ((apr_atomic_win32_ptr_val_fn)InterlockedExchange)(mem, val);
#endif
}

我从这个函数学到两点:

1. 函数其实和变量一样,类型也是可以转换滴(现在想想也是,函数其实也就是地址或者是指针)

2.在一个项目中类型命名要统一,想Apache中,所有用到的类型都用atpr_*重新定义了一边,保证了整个项目数据类型的一致性

尤其对第二点,我是深有感悟,在我现在负责项目的第一期时,我们定义数据类型是用文档来说明的,当时有一个结构的一个字段说明为32位无符号整型,不知道定义该结构的成员怎么想的用了一个UINT_PTR类型,而UINT_PTR在32位系统中是32位,在64位系统中又成了64位了,开始调试阶段我们一直用的32位程序,没有问题,最后在64位机器上测试就有问题了,服务器端是64位,客户端是32位了,客户端的数据就不对了,在发布64位服务器端时,已经发布了32位的服务器端和客户端,为了兼容以前版本,我们做了很多根本不必要做的工作。

现在我在项目就学习了Apache的这一点,对项目数据类型重新定义,统一成一个版本的,摈弃那些有歧义的类型。

看了上面的几个函数,而后的其他函数都类似,直接操作不同而已,这里就不做一一赘述了。

抱歉!评论已关闭.