您的位置:首页 > 编程语言 > PHP开发

php Hash Table(三) Hash Table初始化

2015-09-24 17:28 591 查看
HashTable初始化,在使用HashTable之前要先执行初始化,下边就看看初始化时都做了什么,

Zend/zend_hash.c



staticconstBucket*uninitialized_bucket=NULL;//声明一个全局Bucket*

ZEND_APIint_zend_hash_init(HashTable*ht,uintnSize,hash_func_tpHashFunction,dtor_func_tpDestructor,zend_boolpersistentZEND_FILE_LINE_DC)
{
uinti=3;  /*初始化HashTable大小时,是按照2的整数次幂来初始化,最小为2的3次幂*/

SET_INCONSISTENT(HT_OK);  /*调试用,初始化当前HashTable的状态*/

if(nSize>=0x80000000){
/*HashTable的最大值,防止溢出*/
ht->nTableSize=0x80000000;
}else{
while((1U<<i)<nSize){
i++;
}
ht->nTableSize=1<<i;
}

ht->nTableMask=0;/*0表示ht->arBuckets还没有初始化*/
ht->pDestructor=pDestructor;  /*设置析构函数为传入的函数指针*/
ht->arBuckets=(Bucket**)&uninitialized_bucket;
ht->pListHead=NULL;
ht->pListTail=NULL;
ht->nNumOfElements=0;
ht->nNextFreeElement=0;
ht->pInternalPointer=NULL;
ht->persistent=persistent;
ht->nApplyCount=0;
ht->bApplyProtection=1;
returnSUCCESS;
}



ht是一个指向HashTable变量的指针,它可以定义为直接值形式,也可以通过emalloc()/pemalloc()动态分配,或者更常见的是使用ALLOC_HASHTABLE(ht).ALLOC_HASHTABLE()宏使用了一个特定内存池的预分配块来降低内存分配所需的时间,相比于ht=emalloc(sizeof(HashTable));它通常是首选.

nSize应该被设置为HashTable期望存储的最大元素个数.如果向这个HashTable中尝试增加多于这个数的元素,它将会自动增长,不过有一点需要注意的是,这里Zend重建整个新扩展的HashTable的索引的过程需要耗费不少的处理时间.如果nSize不是2的幂,它将被按照下面公式扩展为下一个2的幂:

nSize=pow(2,ceil(log(nSize,2)));

pHashFunction是旧版本Zend引擎的遗留参数,它不在使用,因此这个值应该被设置为NULL.在早期的Zend引擎中,这个值指向一个用以替换标准的DJBX33A(一种常见的抗碰撞哈希算法,用来将任意字符串key转换到可重演的整型值)的可选哈希算法.

pDestructor指向当从HashTable删除元素时应该被调用的函数,比如当使用zend_hash_del()删除或使用zend_hash_update()替换.析构器函数的原型如下:

voidmethod_name(void*pElement);

pElement指向指向要从HashTable中删除的元素.

persistent它只是一个简单的标记,引擎会直接传递给pemalloc()函数.所有需要保持跨请求可用的HashTable都必须设置这个标记,并且必须调用pemalloc()分配.

可见,zend_hash_init并没有为存放buckets申请内存空间,只是设置了初始化的size,并且设置了nTableMask为0,表示ht->arBuckets还未初始化。整个HashTable的size是按照2的整数次幂申请的,最小为2的3次幂,若空间不够则尝试2的4次幂、2的5次幂……直到大于传入的size。

那么buckets的空间是什么时候申请的呢?答案就是在操作HashTable的时候,看下一篇。~..~


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: