稍微读了一下源码,记录一些我认为有必要的东西,只是为了以防老年痴呆!由于整体的源码还没有看得很清楚,所以大量的错误是允许的,此篇笔记也会一直处于 查询-修改 的迭代过程。
首先拿mapping开刀
mapping其实就是C++中的multimap,但是支持更多。
array values(mapping)。这个方法可以返回所有mapping中的value,那么values()究竟作了什么呢?源码中是这样定义的:
1 PMOD_EXPORT struct array *mapping_values(struct mapping *m) 2 { 3 INT32 e; 4 struct keypair *k; 5 struct array *a; 6 struct svalue *s; 7 8 #ifdef PIKE_DEBUG 9 if(m->data->refs <=0) 10 Pike_fatal("Zero refs in mapping->data\n"); 11 #endif 12 13 check_mapping_for_destruct(m); 14 15 a=allocate_array(m->data->size); 16 s=ITEM(a); 17 18 /* no locking required */ 19 NEW_MAPPING_LOOP(m->data) assign_svalue(s++, & k->val); 20 21 a->type_field = m->data->val_types; 22 23 #ifdef PIKE_DEBUG 24 if(d_flag > 1) check_mapping_type_fields(m); 25 #endif 26 27 return a; 28 }
可以看到,在第15行直接申请了足够存储所有value的内存大小,第19行是一个宏,其循环了所有的可能的value,然后assign_svalue就会将每个k->value给拷贝到返回值array中,并且在27行返回a。
mapping也可以将字符串作为key的,但是它是如何依靠一个ke=string来迅速地找到对应的value的呢?其实mapping使用的siphash(维基百科, 原著论文)来哈希字符串的,也就是先将字符串哈希成一个值,再跟其他的key的哈希值来匹配,这样就容易找到了。如果有兴趣可以看pike中的实现:
1 static size_t low_hashmem_siphash24( const void *s, size_t len, size_t nbytes, size_t key ) 2 { 3 const unsigned char * in = (const unsigned char*)s; 4 unsigned long long inlen = MINIMUM(len, nbytes); 5 6 /* "some pseudo randomly generated bytes" 伪随机产生的字节 */ 7 unsigned INT64 v0 = 0x736f6d6570736575ULL; 8 unsigned INT64 v1 = 0x646f72616e646f6dULL; 9 unsigned INT64 v2 = 0x6c7967656e657261ULL; 10 unsigned INT64 v3 = 0x7465646279746573ULL; 11 unsigned INT64 b; 12 unsigned INT64 k0 = (unsigned INT64)key; 13 unsigned INT64 k1 = (unsigned INT64)key; 14 unsigned INT64 m; 15 const unsigned char *end = in + inlen - ( inlen % sizeof( unsigned INT64 ) ); 16 const int left = inlen & 7; 17 b = ( ( unsigned INT64 )inlen ) << 56; 18 v3 ^= k1; 19 v2 ^= k0; 20 v1 ^= k1; 21 v0 ^= k0; 22 23 for ( ; in != end; in += 8 ) 24 { 25 m = U8TO64_LE( in ); 26 v3 ^= m; 27 SIPROUND; 28 SIPROUND; 29 v0 ^= m; 30 } 31 32 switch( left ) 33 { 34 case 7: b |= ( ( unsigned INT64 )in[ 6] ) << 48; 35 36 case 6: b |= ( ( unsigned INT64 )in[ 5] ) << 40; 37 38 case 5: b |= ( ( unsigned INT64 )in[ 4] ) << 32; 39 40 case 4: b |= ( ( unsigned INT64 )in[ 3] ) << 24; 41 42 case 3: b |= ( ( unsigned INT64 )in[ 2] ) << 16; 43 44 case 2: b |= ( ( unsigned INT64 )in[ 1] ) << 8; 45 46 case 1: b |= ( ( unsigned INT64 )in[ 0] ); break; 47 48 case 0: break; 49 } 50 51 v3 ^= b; 52 SIPROUND; 53 SIPROUND; 54 v0 ^= b; 55 v2 ^= 0xff; 56 SIPROUND; 57 SIPROUND; 58 SIPROUND; 59 SIPROUND; 60 b = v0 ^ v1 ^ v2 ^ v3; 61 return (size_t)b; 62 }
low_hashmen_siphash24
时间: 2024-10-19 02:05:27