Annotation of parser3/src/main/pa_hash.C, revision 1.23

1.1       paf         1: /*
1.19      paf         2:        Parser
                      3:        Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.20      paf         4:        Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.19      paf         5: 
1.23    ! paf         6:        $Id: pa_hash.C,v 1.22 2001/03/18 12:10:56 paf Exp $
1.1       paf         7: */
                      8: 
                      9: /*
                     10:        The prime numbers used from zend_hash.c,
                     11:        the part of Zend scripting engine library,
                     12:        Copyrighted (C) 1999-2000    Zend Technologies Ltd.
                     13:        http://www.zend.com/license/0_92.txt
                     14:        For more information about Zend please visit http://www.zend.com/
                     15: */
                     16: 
1.23    ! paf        17: #include <string.h>
        !            18: 
1.11      paf        19: #include "pa_hash.h"
1.4       paf        20: #include "pa_threads.h"
1.2       paf        21: 
1.8       paf        22: void *Hash::Pair::operator new(size_t size, Pool& apool) {
                     23:        return apool.malloc(size);
1.2       paf        24: }
                     25: 
1.1       paf        26: /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */
1.18      paf        27: uint Hash::allocates[]={
1.1       paf        28:        5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, 
                     29:        16229, 32531, 65407, 130987, 262237, 524521, 1048793, 
                     30:        2097397, 4194103, 8388857, 16777447, 33554201, 67108961, 
                     31:        134217487, 268435697, 536870683, 1073741621, 2147483399};
1.18      paf        32: int Hash::allocates_count=
                     33:        sizeof(allocates)/sizeof(uint);
1.1       paf        34: 
                     35: 
1.13      paf        36: void Hash::construct(Pool& apool, bool athread_safe) {
                     37:        thread_safe=athread_safe;
1.1       paf        38:        
1.18      paf        39:        allocated=allocates[allocates_index=0];
                     40:        threshold=allocated*THRESHOLD_PERCENT/100;
1.1       paf        41:        used=0;
1.18      paf        42:        refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated));
1.1       paf        43: }
                     44: 
                     45: void Hash::expand() {
1.18      paf        46:        int old_size=allocated;
1.2       paf        47:        Pair **old_refs=refs;
1.4       paf        48: 
1.2       paf        49:        // allocated bigger refs array
1.18      paf        50:        allocates_index=allocates_index+1<allocates_count?allocates_index+1:allocates_count-1;
                     51:        allocated=allocates[allocates_index];
                     52:        refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated));
1.1       paf        53: 
                     54:        // rehash
1.2       paf        55:        Pair **old_ref=old_refs;
                     56:        for(int old_index=0; old_index<old_size; old_index++)
                     57:                for(Pair *pair=*old_ref++; pair; ) {
                     58:                        Pair *linked_pair=pair->link;
                     59: 
1.18      paf        60:                        uint new_index=pair->code%allocated;
1.2       paf        61:                        Pair **new_ref=&refs[new_index];
                     62:                        pair->link=*new_ref;
                     63:                        *new_ref=pair;
1.1       paf        64: 
1.2       paf        65:                        pair=linked_pair;
                     66:                }
1.1       paf        67: }
                     68: 
1.18      paf        69: uint Hash::generic_code(uint aresult, const char *start, uint allocated) {
1.1       paf        70:        uint result=aresult, g;
1.18      paf        71:        const char *end=start+allocated;
1.1       paf        72: 
                     73:        while (start<end) {
                     74:                result=(result<<4)+*start++;
                     75:                if ((g=(result&0xF0000000))) {
                     76:                        result=result^(g>>24);
                     77:                        result=result^g;
                     78:                }
                     79:        }
                     80:        return result;
                     81: }
                     82: 
1.17      paf        83: bool Hash::put(const Key& key, Value *value) {  SYNCHRONIZED(thread_safe);
1.1       paf        84:        if(full()) 
                     85:                expand();
                     86: 
1.2       paf        87:        uint code=key.hash_code();
1.18      paf        88:        uint index=code%allocated;
1.2       paf        89:        Pair **ref=&refs[index];
                     90:        for(Pair *pair=*ref; pair; pair=pair->link)
                     91:                if(pair->code==code && pair->key==key) {
                     92:                        // found a pair with the same key
                     93:                        pair->value=value;
1.17      paf        94:                        return true;
1.1       paf        95:                }
1.2       paf        96:        
1.7       paf        97:        // proper pair not found -- create&link_in new pair
1.17      paf        98:        if(!*ref) // root cell were used?
                     99:                used++; // not, we'll use it and record the fact
1.15      paf       100:        *ref=NEW Pair(code, key, value, *ref);
1.17      paf       101:        return false;
1.1       paf       102: }
                    103: 
1.13      paf       104: Hash::Value *Hash::get(const Key& key) const {  SYNCHRONIZED(thread_safe);
1.2       paf       105:        uint code=key.hash_code();
1.18      paf       106:        uint index=code%allocated;
1.2       paf       107:        for(Pair *pair=refs[index]; pair; pair=pair->link)
1.1       paf       108:                if(pair->code==code && pair->key==key)
                    109:                        return pair->value;
                    110:        
                    111:        return 0;
                    112: }
1.16      paf       113: 
1.17      paf       114: bool Hash::put_replace(const Key& key, Value *value) {  SYNCHRONIZED(thread_safe);
1.16      paf       115:        uint code=key.hash_code();
1.18      paf       116:        uint index=code%allocated;
1.16      paf       117:        for(Pair *pair=refs[index]; pair; pair=pair->link)
                    118:                if(pair->code==code && pair->key==key) {
                    119:                        // found a pair with the same key, replacing
                    120:                        pair->value=value;
                    121:                        return true;
                    122:                }
                    123: 
                    124:        // proper pair not found 
                    125:        return false;
                    126: }
                    127: 
1.17      paf       128: bool Hash::put_dont_replace(const Key& key, Value *value) {  SYNCHRONIZED(thread_safe);
                    129:        if(full()) 
                    130:                expand();
                    131: 
                    132:        uint code=key.hash_code();
1.18      paf       133:        uint index=code%allocated;
1.17      paf       134:        Pair **ref=&refs[index];
                    135:        for(Pair *pair=*ref; pair; pair=pair->link)
                    136:                if(pair->code==code && pair->key==key) {
                    137:                        // found a pair with the same key, NOT replacing
                    138:                        return true;
                    139:                }
                    140: 
                    141:        // proper pair not found -- create&link_in new pair
                    142:        *ref=NEW Pair(code, key, value, *ref);
                    143:        if(!*ref) // root cell were used?
                    144:                used++; // not, we'll use it and record the fact
                    145:        return false;
                    146: }
                    147: 
                    148: void Hash::merge_dont_replace(const Hash& src) {  SYNCHRONIZED(thread_safe);
1.18      paf       149:        for(int i=0; i<src.allocated; i++)
1.17      paf       150:                for(Pair *pair=src.refs[i]; pair; pair=pair->link)
                    151:                        put_dont_replace(pair->key, pair->value);
1.18      paf       152:        // MAY:optimize this.allocated==src.allocated case
1.21      paf       153: }
                    154: 
                    155: void Hash::foreach(Foreach_func func, void *info) {
                    156:        Pair **ref=refs;
                    157:        for(int index=0; index<allocated; index++)
                    158:                for(Pair *pair=*ref++; pair; pair=pair->link)
1.22      paf       159:                        (*func)(pair->key, pair->value, info);
1.23    ! paf       160: }
        !           161: 
        !           162: void Hash::clear() {  SYNCHRONIZED(thread_safe);
        !           163:        memset(refs, 0, sizeof(*refs)*allocated);
        !           164:        used=0;
1.17      paf       165: }

E-mail: