Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

hash.h

00001 /*
00002  *                         Sun Public License Notice
00003  *
00004  * The contents of this file are subject to the Sun Public License
00005  * Version 1.0 (the "License"); you may not use this file except
00006  * in compliance with the License. A copy of the License is available
00007  * at http://www.sun.com/
00008  *
00009  * The Original Code is the Java Profiler module.  The Initial Developers
00010  * of the Original Code are Jan Stola, Pavel Vacha, Michal Pise, Petr Luner,
00011  * Lukas Petru and Marek Przeczek.
00012  *
00013  * Portions created by Jan Stola are Copyright (C) 2000-2001.
00014  * All Rights Reserved.
00015  *
00016  * Portions created by Pavel Vacha are Copyright (C) 2000-2001.
00017  * All Rights Reserved.
00018  *
00019  * Portions created by Michal Pise are Copyright (C) 2000-2001.
00020  * All Rights Reserved.
00021  *
00022  * Portions created by Petr Luner are Copyright (C) 2000-2001.
00023  * All Rights Reserved.
00024  *
00025  * Portions created by Lukas Petru are Copyright (C) 2000-2001.
00026  * All Rights Reserved.
00027  *
00028  * Portions created by Marek Przeczek are Copyright (C) 2000-2001.
00029  * All Rights Reserved.
00030  *
00031  * Contributors: Jan Stola, Pavel Vacha, Michal Pise, Petr Luner,
00032  *               Lukas Petru and Marek Przeczek.
00033  */
00034 
00035 #ifndef _HASH_H_
00036 #define _HASH_H_
00037 
00038 #include "../main/includes.h"
00039 #include "../list/list.h"
00040 
00081 template<class T, class K, class L> class Hash {
00082 
00084         enum e {
00085                 
00087                 HASH_LIST_LIMIT = 3
00088         };
00089 
00090 private:
00091 
00093         List<T,L>* _table;
00094 
00096         unsigned int _size;
00097 
00099         unsigned int _mask;
00100 
00102         unsigned int _numItems;
00103 
00105         unsigned int _index;
00106 
00107 public:
00108 
00110         Hash() :
00111 
00112                 _size( 1<<10),
00113                 _numItems( 0),
00114                 _index(0) {
00115         
00116                 _table = new List<T,L>[_size];
00117                 _mask = _size-1;
00118         }
00119 
00121         ~Hash() { delete[] _table;}
00122 
00126         void clear() {
00127 
00128                 List<T,L>* p = _table;
00129                 for( unsigned int i = 0; i < _size; i++, p++) p->clear();
00130         }
00131 
00139         T* first() {
00140 
00141                 List<T,L>* p = _table;
00142                 T* q;
00143 
00144                 for( _index = 0; _index < _size; _index++, p++)
00145                         if( q = p->first()) return q;
00146 
00147                 return NULL;
00148         }
00149 
00159         T* next( T* item) {
00160 
00161                 T* q = static_cast<T*>( static_cast<L*>( item->L::next()));
00162                 if( q) return q;
00163 
00164                 List<T,L>* p = &_table[++_index];
00165 
00166                 for( ; _index < _size; _index++)
00167                         if( q = p->first()) return q;
00168 
00169                 return NULL;
00170         }
00171 
00180         T* addNoRehash( T* item) {
00181         
00182                 if( !item) return NULL;
00183 
00184                 K key;
00185                 int h = T::hashKey( item->getKey( key));
00186 
00187                 _table[makeIndex( h)].add( item);
00188                 _numItems++;
00189 
00190                 return item;
00191         }
00192 
00201         T* add( T* item) {
00202 
00203                 if( !addNoRehash( item)) return NULL;
00204                 if( _numItems > _size*HASH_LIST_LIMIT+5) rehash( _size<<1);
00205 
00206                 return item;
00207         }
00208 
00217         T* removeNoRehash( T* item) {
00218 
00219                 if( !item) return NULL;
00220 
00221 
00222                 item->L::remove();
00223                 _numItems--;
00224 
00225                 return item;
00226         }
00227 
00236         T* remove( T* item) {
00237 
00238                 if( !removeNoRehash( item)) return NULL;
00239 
00240                 unsigned int sz = _size>>1;
00241                 if( _numItems < sz*HASH_LIST_LIMIT) rehash( sz);
00242 
00243                 return item;
00244         }
00245 
00254         T* get( const K& key) {
00255 
00256                 int h = T::hashKey( key);
00257                 List<T,L>* list = &_table[makeIndex( h)];
00258                 T* p = list->first();
00259 
00260                 while( p && !(*p == key)) p = list->next( p);
00261 
00262                 if( p) list->add( list->remove( p));
00263 
00264                 return p;
00265         }
00266 
00283         int forEach( int (*f)( T*, void**), void** inout) {
00284         
00285                 List<T,L>* p = _table;
00286         
00287                 for( unsigned int i = 0; i < _size; i++, p++) {
00288         
00289                         int rc = p->forEach( f, inout);
00290                         if( rc) return rc;
00291                 }
00292 
00293                 return 0;
00294         }
00295 
00296 private:
00297 
00306         unsigned int makeIndex( int x) {
00307 
00308                 unsigned int key = (unsigned)x;
00309 
00310                 key += (key << 12);
00311                 key ^= (key >> 22);
00312                 key += (key << 4);
00313                 key ^= (key >> 9);
00314                 key += (key << 10);
00315                 key ^= (key >> 2);
00316                 key += (key << 7);
00317                 key ^= (key >> 12);
00318 
00319                 unsigned int index = key & _mask;
00320                 if( index >= _size) index >>= 1;
00321 
00322                 return index;
00323         }
00324 
00330         void rehash( unsigned int sz) {
00331 
00332                 unsigned int size = _size;
00333                 List<T,L>* table = _table;
00334 
00335                 _size = sz;
00336                 _table = new List<T,L>[_size];
00337 
00338                 _mask = _size-1;
00339                 _numItems = 0;
00340 
00341                 _index = 0;
00342 
00343                 List<T,L>* p = table;
00344         
00345                 for( unsigned int i = 0; i < size; i++, p++)
00346                         while( addNoRehash( p->remove( p->first())));
00347 
00348                 delete[] table;
00349         }
00350 
00351 #ifdef _DEBUG
00352 public:
00353 
00358         void printStatistics() const {
00359 
00360                 cout << "table size: "  << _size     << endl;
00361                 cout << "total items: " << _numItems << endl;
00362 
00363                 if( !_size) return;
00364 
00365                 unsigned int max = 0, len;
00366                 unsigned int i, j;
00367 
00368                 List<T,L>* p;
00369                 int hist[10];
00370 
00371                 for( i = 0, p = _table; i < _size; i++, p++)
00372                         if ((len = p->length()) > max) max = len;
00373 
00374                 memset( hist, 0, 10*sizeof(int));
00375 
00376                 for( i = 0, p = _table; i < _size; i++, p++) {
00377 
00378                         len = p->length();
00379                         for( j = 0; j < 10; j++)
00380 
00381                                 if( len <= max*(j+1)/10) {
00382 
00383                                         hist[j]++;
00384                                         break;
00385                                 }
00386                 }
00387 
00388                 cout << "distribution of list length:" << endl;
00389                 for( j = 0; j < 10; j++)
00390                         cout << max*j/10 << " - " << max*(j+1)/10 << " items: " << (hist[j]*100)/_size << "%" << endl;
00391         }
00392 #endif
00393 };
00394 
00395 #endif // _HASH_H_

Generated on Mon Jan 28 14:53:26 2002 for Java Profiler Dynamic Library by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001