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

sc_hash.cpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2004 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.3 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 
00018 /*****************************************************************************
00019 
00020   sc_hash.cpp -- Implementation of a chained hash table with MTF
00021                  (move-to-front).
00022 
00023   Original Author: Stan Y. Liao, Synopsys, Inc.
00024 
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028 
00029   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
00030   changes you are making here.
00031 
00032       Name, Affiliation, Date:
00033   Description of Modification:
00034 
00035  *****************************************************************************/
00036 
00037 
00038 #include <assert.h>
00039 #include <stdlib.h>
00040 
00041 #include "systemc/kernel/sc_cmnhdr.h"
00042 #include "systemc/utils/sc_hash.h"
00043 #include "systemc/utils/sc_mempool.h"
00044 
00045 
00046 const double PHASH_DEFAULT_GROW_FACTOR     = 2.0;
00047 
00048 class sc_phash_elem {
00049     friend class sc_phash_base;
00050     friend class sc_phash_base_iter;
00051 
00052 private:
00053     void* key;
00054     void* contents;
00055     sc_phash_elem* next;
00056 
00057     sc_phash_elem( void* k, void* c, sc_phash_elem* n )
00058         : key(k), contents(c), next(n) { }
00059     sc_phash_elem() { }
00060     ~sc_phash_elem() { }
00061 
00062     static void* operator new(size_t sz)            { return sc_mempool::allocate(sz); }
00063     static void operator delete(void* p, size_t sz) { sc_mempool::release(p, sz);      }
00064 };
00065 
00066 
00067 sc_phash_base::sc_phash_base(
00068     void* def,
00069     int size,
00070     int density,
00071     double grow,
00072     bool reorder,
00073     unsigned (*hash_fn)(const void*),
00074     int (*cmp_fn)(const void*, const void*)
00075 )
00076 {
00077     default_value = def;
00078     hash          = hash_fn;
00079     num_entries   = 0;
00080     max_density   = density;
00081     grow_factor   = grow;
00082     reorder_flag  = reorder;
00083 
00084     if (size <= 0)
00085         size = PHASH_DEFAULT_INIT_TABLE_SIZE;
00086     else if ((size % 2) == 0)
00087         size += 1;
00088     num_bins = size;
00089     bins = new sc_phash_elem*[size];
00090     for (int i = 0; i < size; ++i)
00091         bins[i] = 0;
00092 
00093     set_cmpr_fn(cmp_fn);
00094 }
00095 
00096 void
00097 sc_phash_base::set_cmpr_fn(cmpr_fn_t c)
00098 {
00099     cmpr = c;
00100 }
00101 
00102 void
00103 sc_phash_base::set_hash_fn(hash_fn_t h)
00104 {
00105     hash = h;
00106 }
00107 
00108 sc_phash_base::~sc_phash_base()
00109 {
00110     sc_phash_elem* ptr;
00111     sc_phash_elem* next;
00112 
00113     for (int i = 0; i < num_bins; ++i) {
00114         ptr = bins[i];
00115         while (ptr != 0) {
00116             next = ptr->next;
00117             delete ptr;
00118             ptr = next;
00119         }
00120     }
00121     delete[] bins;
00122 }
00123 
00124 void
00125 sc_phash_base::rehash()
00126 {
00127     sc_phash_elem* ptr;
00128     sc_phash_elem* next;
00129     sc_phash_elem** old_bins = bins;
00130 
00131     int old_num_bins = num_bins;
00132     unsigned hash_val;
00133 
00134     num_bins = (int) (grow_factor * old_num_bins);
00135     if (num_bins % 2 == 0)
00136         ++num_bins;
00137 
00138     num_entries = 0;
00139     bins = new sc_phash_elem*[num_bins];
00140     memset( bins, 0, sizeof(sc_phash_elem*) * num_bins );
00141 
00142     for (int i = 0; i < old_num_bins; ++i) {
00143         ptr = old_bins[i];
00144         while (ptr != 0) {
00145             next = ptr->next;
00146             hash_val = do_hash(ptr->key);
00147             ptr->next = bins[hash_val];
00148             bins[hash_val] = ptr;
00149             ++num_entries;
00150             ptr = next;
00151         }
00152     }
00153     delete[] old_bins;
00154 }
00155 
00156 sc_phash_elem*
00157 sc_phash_base::find_entry_q( unsigned hash_val, const void* key, sc_phash_elem*** plast )
00158 {
00159     sc_phash_elem** last = &(bins[hash_val]);
00160     sc_phash_elem*  ptr  = *last;
00161 
00162     /* The (ptr->key != key) here is meant by the "q" */
00163     while ((ptr != 0) && (ptr->key != key)) {
00164         /*                         ^^ right here */
00165         last = &(ptr->next);
00166         ptr  = *last;
00167     }
00168     if ((ptr != 0) && reorder_flag) {
00169         *last = ptr->next;
00170         ptr->next = bins[hash_val];
00171         bins[hash_val] = ptr;
00172         last = &(bins[hash_val]);
00173     }
00174     if (plast) *plast = last;
00175     return ptr;
00176 }
00177 
00178 sc_phash_elem*
00179 sc_phash_base::find_entry_c( unsigned hash_val, const void* key, sc_phash_elem*** plast )
00180 {
00181     sc_phash_elem** last = &(bins[hash_val]);
00182     sc_phash_elem*  ptr  = *last;
00183 
00184     while ((ptr != 0) && ((*cmpr)(ptr->key, key) != 0)) {
00185         last = &(ptr->next);
00186         ptr = *last;
00187     }
00188         /* Bring to front */
00189     if ((ptr != 0) && reorder_flag) {
00190         *last = ptr->next;
00191         ptr->next = bins[hash_val];
00192         bins[hash_val] = ptr;
00193         last = &(bins[hash_val]);
00194     }
00195     if (plast) *plast = last;
00196     return ptr;
00197 }
00198 
00199 sc_phash_elem*
00200 sc_phash_base::add_direct( void* key, void* contents, unsigned hash_val )
00201 {
00202     if (num_entries / num_bins >= max_density) {
00203         rehash();
00204         hash_val = do_hash(key);
00205     }
00206 
00207     sc_phash_elem* new_entry = new sc_phash_elem(key, contents, bins[hash_val]);
00208     bins[hash_val] = new_entry;
00209     ++num_entries;
00210     return new_entry;
00211 }
00212 
00213 void
00214 sc_phash_base::erase()
00215 {
00216     for (int i = 0; i < num_bins; ++i) {
00217         sc_phash_elem* ptr = bins[i];
00218         while (ptr != 0) {
00219             sc_phash_elem* next = ptr->next;
00220             delete ptr;
00221             ptr = next;
00222             --num_entries;
00223         }
00224         bins[i] = 0;
00225     }
00226     assert(num_entries == 0);
00227 }
00228 
00229 void
00230 sc_phash_base::erase(void (*kfree)(void*))
00231 {
00232     for (int i = 0; i < num_bins; ++i) {
00233         sc_phash_elem* ptr = bins[i];
00234         while (ptr != 0) {
00235             sc_phash_elem* next = ptr->next;
00236             (*kfree)(ptr->key);
00237             delete ptr;
00238             ptr = next;
00239             --num_entries;
00240         }
00241         bins[i] = 0;
00242     }
00243     assert(num_entries == 0);
00244 }
00245 
00246 void
00247 sc_phash_base::copy( const sc_phash_base* b )
00248 {
00249     erase();
00250     iterator iter((sc_phash_base*) b);  /* cast away the const */
00251     for ( ; ! iter.empty(); iter++)
00252         insert( iter.key(), iter.contents() );
00253 }
00254 
00255 void
00256 sc_phash_base::copy(const sc_phash_base& b, void* (*kdup)(const void*), void (*kfree)(void*))
00257 {
00258     erase(kfree);
00259     iterator iter((sc_phash_base&) b);
00260     for ( ; ! iter.empty(); iter++)
00261         insert( (*kdup)(iter.key()), iter.contents() );
00262 }
00263 
00264 int
00265 sc_phash_base::insert( void* k, void* c )
00266 {
00267     unsigned hash_val = do_hash(k);
00268     sc_phash_elem* ptr = find_entry( hash_val, k );
00269     if (ptr == 0) {
00270         (void) add_direct(k, c, hash_val);
00271         return 0;
00272     }
00273     else {
00274         ptr->contents = c;
00275         return 1;
00276     }
00277 }
00278 
00279 int
00280 sc_phash_base::insert( void* k, void* c, void* (*kdup)(const void*) )
00281 {
00282     unsigned hash_val = do_hash(k);
00283     sc_phash_elem* ptr = find_entry( hash_val, k );
00284     if (ptr == 0) {
00285         (void) add_direct((*kdup)(k), c, hash_val);
00286         return 0;
00287     }
00288     else {
00289         ptr->contents = c;
00290         return 1;
00291     }
00292 }
00293 
00294 int
00295 sc_phash_base::insert_if_not_exists( void* k, void* c )
00296 {
00297     unsigned hash_val = do_hash(k);
00298     sc_phash_elem* ptr = find_entry( hash_val, k );
00299     if (ptr == 0) {
00300         (void) add_direct( k, c, hash_val );
00301         return 0;
00302     }
00303     else
00304         return 1;
00305 }
00306 
00307 int
00308 sc_phash_base::insert_if_not_exists( void* k, void* c, void* (*kdup)(const void*) )
00309 {
00310     unsigned hash_val = do_hash(k);
00311     sc_phash_elem* ptr = find_entry( hash_val, k );
00312     if (ptr == 0) {
00313         (void) add_direct( (*kdup)(k), c, hash_val );
00314         return 0;
00315     }
00316     else
00317         return 1;
00318 }
00319 
00320 int
00321 sc_phash_base::remove( const void* k )
00322 {
00323     unsigned hash_val = do_hash(k);
00324     sc_phash_elem** last;
00325     sc_phash_elem*  ptr = find_entry( hash_val, k, &last );
00326 
00327     if (ptr == 0)
00328         return 0;
00329 
00330     assert(*last == ptr);
00331     *last = ptr->next;
00332     delete ptr;
00333     --num_entries;
00334     return 1;
00335 }
00336 
00337 int
00338 sc_phash_base::remove( const void* k, void** pk, void** pc )
00339 {
00340     unsigned hash_val = do_hash(k);
00341     sc_phash_elem** last;
00342     sc_phash_elem*  ptr = find_entry( hash_val, k, &last );
00343 
00344     if (ptr == 0) {
00345         *pk = 0;
00346         *pc = 0;
00347         return 0;
00348     }
00349     else {
00350         *pk = ptr->key;
00351         *pc = ptr->contents;
00352     }
00353 
00354     assert(*last == ptr);
00355     *last = ptr->next;
00356     delete ptr;
00357     --num_entries;
00358     return 1;
00359 }
00360 
00361 int
00362 sc_phash_base::remove(const void* k, void (*kfree)(void*))
00363 {
00364     void* rk;
00365     void* rc;
00366     if (remove(k, &rk, &rc)) {
00367         (*kfree)(rk);
00368         return 1;
00369     }
00370     else
00371         return 0;
00372 }
00373 
00374 int
00375 sc_phash_base::remove_by_contents( const void* c )
00376 {
00377     sc_phash_elem** last;
00378     sc_phash_elem*  ptr;
00379 
00380     int num_removed = 0;
00381     for (int i = 0; i < num_bins; ++i) {
00382         last = &(bins[i]);
00383         ptr = *last;
00384         while (ptr != 0) {
00385             if (ptr->contents != c) {
00386                 last = &(ptr->next);
00387                 ptr  = *last;
00388             }
00389             else {
00390                 *last = ptr->next;
00391                 delete ptr;
00392                 ptr = *last;
00393                 --num_entries;
00394                 ++num_removed;
00395             }
00396         }
00397     }
00398     return num_removed;
00399 }
00400 
00401 int
00402 sc_phash_base::remove_by_contents( bool (*predicate)(const void* c, void* arg), void* arg )
00403 {
00404     sc_phash_elem** last;
00405     sc_phash_elem*  ptr;
00406 
00407     int num_removed = 0;
00408     for (int i = 0; i < num_bins; ++i) {
00409         last = &(bins[i]);
00410         ptr = *last;
00411         while (ptr != 0) {
00412             if (! (*predicate)(ptr->contents, arg)) {
00413                 last = &(ptr->next);
00414                 ptr  = *last;
00415             }
00416             else {
00417                 *last = ptr->next;
00418                 delete ptr;
00419                 ptr = *last;
00420                 --num_entries;
00421                 ++num_removed;
00422             }
00423         }
00424     }
00425     return num_removed;
00426 }
00427 
00428 int
00429 sc_phash_base::remove_by_contents( const void* c, void (*kfree)(void*) )
00430 {
00431     sc_phash_elem** last;
00432     sc_phash_elem*  ptr;
00433 
00434     int num_removed = 0;
00435     for (int i = 0; i < num_bins; ++i) {
00436         last = &(bins[i]);
00437         ptr = *last;
00438         while (ptr != 0) {
00439             if (ptr->contents != c) {
00440                 last = &(ptr->next);
00441                 ptr  = *last;
00442             }
00443             else {
00444                 *last = ptr->next;
00445                 (*kfree)(ptr->key);
00446                 delete ptr;
00447                 ptr = *last;
00448                 --num_entries;
00449                 ++num_removed;
00450             }
00451         }
00452     }
00453     return num_removed;
00454 }
00455 
00456 int
00457 sc_phash_base::remove_by_contents( bool (*predicate)(const void*, void*), void* arg, void (*kfree)(void*))
00458 {
00459     sc_phash_elem** last;
00460     sc_phash_elem*  ptr;
00461 
00462     int num_removed = 0;
00463     for (int i = 0; i < num_bins; ++i) {
00464         last = &(bins[i]);
00465         ptr = *last;
00466         while (ptr != 0) {
00467             if (! (*predicate)(ptr->contents, arg)) {
00468                 last = &(ptr->next);
00469                 ptr  = *last;
00470             }
00471             else {
00472                 *last = ptr->next;
00473                 (*kfree)(ptr->key);
00474                 delete ptr;
00475                 ptr = *last;
00476                 --num_entries;
00477                 ++num_removed;
00478             }
00479         }
00480     }
00481     return num_removed;
00482 }
00483 
00484 int
00485 sc_phash_base::lookup( const void* k, void** c_ptr ) const
00486 {
00487     unsigned hash_val = do_hash(k);
00488     sc_phash_elem* ptr = find_entry( hash_val, k );
00489     if (ptr == 0) {
00490         if (c_ptr != 0) *c_ptr = default_value;
00491         return 0;
00492     }
00493     else {
00494         if (c_ptr != 0) *c_ptr = ptr->contents;
00495         return 1;
00496     }
00497 }
00498 
00499 void*
00500 sc_phash_base::operator[]( const void* key ) const
00501 {
00502     void* contents;
00503     lookup( key, &contents );
00504     return contents;
00505 }
00506 
00507 /***************************************************************************/
00508 
00509 void
00510 sc_phash_base_iter::reset( sc_phash_base* t )
00511 {
00512     table = t;
00513     index = 0;
00514     entry = 0;
00515     next  = 0;
00516 
00517     for (int i = index; i < table->num_bins; ++i) {
00518         if (table->bins[i] != 0) {
00519             index = i + 1;
00520             last  = &(table->bins[i]);
00521             entry = *last;
00522             next  = entry->next;
00523             break;
00524         }
00525     }
00526 }
00527 
00528 bool
00529 sc_phash_base_iter::empty() const
00530 {
00531     return (entry == 0);
00532 }
00533 
00534 void
00535 sc_phash_base_iter::step()
00536 {
00537     if (entry) {
00538         last = &(entry->next);
00539     }
00540     entry = next;
00541     if (! entry) {
00542         for (int i = index; i < table->num_bins; ++i) {
00543             if (table->bins[i] != 0) {
00544                 index = i + 1;
00545                 last = &(table->bins[i]);
00546                 entry = *last;
00547                 next = entry->next;
00548                 break;
00549             }
00550         }
00551     }
00552     else {
00553         next = entry->next;
00554     }
00555 }
00556 
00557 void
00558 sc_phash_base_iter::remove()
00559 {
00560     delete entry;
00561     *last = next;
00562     entry = 0;
00563     --table->num_entries;
00564     step();
00565 }
00566 
00567 void
00568 sc_phash_base_iter::remove(void (*kfree)(void*))
00569 {
00570     (*kfree)(entry->key);
00571     delete entry;
00572     *last = next;
00573     entry = 0;
00574     --table->num_entries;
00575     step();
00576 }
00577 
00578 void*
00579 sc_phash_base_iter::key() const
00580 {
00581     return entry->key;
00582 }
00583 
00584 void*
00585 sc_phash_base_iter::contents() const
00586 {
00587     return entry->contents;
00588 }
00589 
00590 void*
00591 sc_phash_base_iter::set_contents( void* c )
00592 {
00593     return entry->contents = c;
00594 }
00595 
00596 /****************************************************************************/
00597 
00598 unsigned 
00599 default_ptr_hash_fn(const void* p)
00600 {
00601     return ((unsigned)(p) >> 2) * 2654435789U;
00602 
00603 }
00604 
00605 unsigned
00606 default_int_hash_fn(const void* p)
00607 {
00608     return (unsigned)(p) * 3141592661U;
00609 }
00610 
00611 
00612 unsigned
00613 default_str_hash_fn(const void* p)
00614 {
00615     if (!p) return 0;
00616 
00617     const char* x = (const char*) p;
00618     unsigned int h = 0;
00619     unsigned int g;
00620 
00621     while (*x != 0) {
00622         h = (h << 4) + *x++;
00623         if ((g = h & 0xf0000000) != 0)
00624             h = (h ^ (g >> 24)) ^ g;
00625     }
00626     return h;
00627 }
00628 
00629 int
00630 sc_strhash_cmp( const void* a, const void* b )
00631 {
00632     return strcmp( (const char*) a, (const char*) b );
00633 }
00634 
00635 void*
00636 sc_strhash_kdup(const void* k)
00637 {
00638     return strdup((const char*) k);
00639 }
00640 
00641 void
00642 sc_strhash_kfree(void* k)
00643 {
00644     if (k) free((char*) k);
00645 }

Generated on Fri Jan 14 08:29:02 2005 for SystemC2.1beta11(excludingMSLib)(IncludingSCV)\nProvidedby:www.openverificationfoundation.org by doxygen1.2.18