Dalvik VM Hash - implementation

原创 2012年03月30日 00:27:28

Dalvik虚拟机 之 哈希表实现篇

前面两篇分别介绍了dvm里哈希表的接口和使用。下面我们来看看dvm里哈希表是怎么实现的。

 

数据结构

/*

* One entry in the hash table. "data" values are expected to be (or have

* the same characteristics as) valid pointers. In particular, a NULL

* value for "data" indicates an empty slot, and HASH_TOMBSTONE indicates

* a no-longer-used slot that must be stepped over during probing.

*

* Attempting to add a NULL or tombstone value is an error.

*

* When an entry is released, we will call (HashFreeFunc)(entry->data).

*/

struct HashEntry {

u4 hashValue;

void* data;

};

该结构表示一个哈希单元。它由两部分,一个四字节空间的哈希值和一个不定长的真正的数据部分。在该单元被清理时,该数据部分所占据的内存会被函数调用(HashFreeFunc)(entry->data)清理掉。该清理函数是在哈希表创建时传入的(dvmHashTableCreate()的第二个参数)。

/*

* Expandable hash table.

*

* This structure should be considered opaque.

*/

struct HashTable {

int tableSize; /* must be power of 2 */

int numEntries; /* current #of "live" entries */

int numDeadEntries; /* current #of tombstone entries */

HashEntry* pEntries; /* array on heap */

HashFreeFunc freeFunc;

pthread_mutex_t lock;

};

该结构表示一个哈希表。其成员变量分别是

tableSize: 哈希表的大小,必须是2的幂次。

numEntries: 当前哈希表用于的有效单元数量

numDeadEntries: 改哈希表拥有的无效单元数量。

pEntries: 表示指向该哈希表单元数据的指针

freeFunc: 哈希表单元释放函数

lock:用于同步访问该哈希表的锁。

 

我们后面会看到,哈希表实现中对于无效单元只是简单的将其哈希值表示为一个常量,而没有调用释放函数:

#define HASH_TOMBSTONE ((void*) 0xcbcacccd) // invalid ptr value

哈希表创建

/*

* Create and initialize a hash table.

*/

HashTable* dvmHashTableCreate(size_t initialSize, HashFreeFunc freeFunc)

{

HashTable* pHashTable;

 

assert(initialSize > 0);

 

pHashTable = (HashTable*) malloc(sizeof(*pHashTable));

if (pHashTable == NULL)

return NULL;

 

dvmInitMutex(&pHashTable->lock);

 

pHashTable->tableSize = dexRoundUpPower2(initialSize);

pHashTable->numEntries = pHashTable->numDeadEntries = 0;

pHashTable->freeFunc = freeFunc;

pHashTable->pEntries =

(HashEntry*) malloc(pHashTable->tableSize * sizeof(HashEntry));

if (pHashTable->pEntries == NULL) {

free(pHashTable);

return NULL;

}

 

memset(pHashTable->pEntries, 0, pHashTable->tableSize * sizeof(HashEntry));

return pHashTable;

}

 

首先用断言检查传入的初始大小必须大于0。然后用malloc分配本地内存最为哈希表的空间。由于分配的是本地内存,该哈希表不会被垃圾收集,并且需要在不使用时调用free()来显式的释放空间,否则将引起内存泄露。接下来初始化访问锁。随后调用dexRoundUpPower2来保证初始大小为2幂次方对齐。将有效单元数量和无效单元数量初始化为0。将参数传入的释放函数存放在freeFunc变量里。接着调用malloc为单元指针分配空间。 最后memset整个单元后返回改哈希表结构指针。

 

 

哈希表清理

 

/*

* Clear out all entries.

*/

void dvmHashTableClear(HashTable* pHashTable)

{

HashEntry* pEnt;

int i;

 

pEnt = pHashTable->pEntries;

for (i = 0; i < pHashTable->tableSize; i++, pEnt++) {

if (pEnt->data == HASH_TOMBSTONE) {

// nuke entry

pEnt->data = NULL;

} else if (pEnt->data != NULL) {

// call free func then nuke entry

if (pHashTable->freeFunc != NULL)

(*pHashTable->freeFunc)(pEnt->data);

pEnt->data = NULL;

}

}

 

pHashTable->numEntries = 0;

pHashTable->numDeadEntries = 0;

}

dvmHashTableClear实现。它遍历每个单元,对于无效的单元,简单的将该单元数据区置为NULL。对有效单元调用释放函数后将数据区置为NULL。

 

 

哈希表释放

/*

* Free the table.

*/

void dvmHashTableFree(HashTable* pHashTable)

{

if (pHashTable == NULL)

return;

dvmHashTableClear(pHashTable);

free(pHashTable->pEntries);

free(pHashTable);

}

首先调用dvmHashTableClear清理多有单元数据,然后free掉哈希表结构中为单元指针分配的内存,最后free掉该哈希表本身占据的内存。

 

 

哈希表查找和插入单元

哈希表查找,插入新单元是被放到同一个函数dvmHashTableLookup里实现的。用最后一个参数doAdd来区分开来。

首次是查找的实现,它从第一个单元开始遍历,如果该单元满足下面的条件

“pEntry->data != HASH_TOMBSTONE  && pEntry->hashValue == itemHash && (*cmpFunc)(pEntry->data, item) == 0”

也就是说必须 不能使无效单元,而且哈希值相等,并且调用比较函数的结果相符(返回值为0)。

如果doAdd为1,则进行插入操作。再插入之前,需要判断当前表示空间是否足够容纳新插入一个单元,不够的话需要扩展空间。

 

哈希表删除

和查找类似,也是根据哈希值找到第一个单元后,比较该单元的数值指针的值和带比较的是否一致。一致的话就表示该单元哈希值为常量HASH_TOMBSTONE。

 

 

 

 

 

 

 

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Dalvik vm Hash interface

Dalvik VM 哈希表 之 接口篇   几乎在所有的高级语言中都有哈希表(hashmap)的支持。它已经成为很多语言内建的数据类型。但是C语言创建较早,没有内建的哈希表类型的支持。我们只能通过...

analysis of dalvik VM

  • 2012-11-30 02:02
  • 709KB
  • 下载

Dalvik VM的启动过程解析

Dalvik 虚拟机的启动要从android另一个著名的模块,Zygote,说起。   我们知道android系统中,每一个java应用被设计成可以运行在一个单独的Linux进程中。而每个...

Dalvik VM Instruction Formats

  • 2011-12-02 14:05
  • 76KB
  • 下载

Dalvik VM document

  • 2013-07-09 18:21
  • 709KB
  • 下载

Dalvik VM启动流程之间单分析

Android system在Kernel初始化玩就会先启动initprocess, 而在init process之中会去启动Zygoteprocess, Zygote process是Android...

Dalvik VM internal

  • 2010-03-22 22:58
  • 813KB
  • 下载

Dalvik VM 簡介

  • 2012-05-02 13:44
  • 2.43MB
  • 下载

JAVA implementation for Locality Sensitive Hash

private int dimention; //维度大小,例如对于sift特征来说就是128private int max; //所需向量中元素可能的上限,譬如对于RGB来说,就是255privat...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)