• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

sst/elements/genericProc/programs/libcprops/hashtable.h

Go to the documentation of this file.
00001 #ifndef _CP_HASHTABLE_H
00002 #define _CP_HASHTABLE_H
00003 
00004 /*
00005  * hash table implementation
00006  */
00007 
00008 /**
00009  * @addtogroup cp_hashtable
00010  * @ingroup collection
00011  * @copydoc collection
00012  *
00013  */
00014 /** @{ */
00015 /**
00016  * @file
00017  * generic synchronized hashtable. 
00018  *
00019  * Here is an example of using a cp_hashtable to create a lookup for 'bar'
00020  * items using 'foo' keys:
00021  *
00022  * <code><pre>
00023  * unsigned long foo_hash_code(void *fooptr) 
00024  * {
00025  *     return ((foo *) fooptr)->id; 
00026  * }    
00027  *
00028  * // compare function
00029  * int foo_compare(void *f1, void *f2)
00030  * {
00031  *     return ((foo *) f1)->id != ((foo *) f2)->id;
00032  * }
00033  *
00034  * ...
00035  * 
00036  *     cp_hashtable *t;
00037  *     foo *foo1, *f;
00038  *     bar *bar1, *bar2;
00039  *     
00040  *     t = cp_hashtable_create(10, foo_hash_code, foo_compare);
00041  *     if (t == NULL) 
00042  *     {
00043  *         perror("can\'t create cp_hashtable");
00044  *         exit(1);
00045  *     }
00046  * 
00047  *     cp_hashtable_put(foo1, bar1, t);
00048  * 
00049  *     ...
00050  *     f = foo_create(...);
00051  *     ...
00052  * 
00053  *     if ((bar2 = (bar *) cp_hashtable_get(f, t))) 
00054  *         printf("%s maps to %s\n", foo_get_name(f), bar_get_name(bar2));
00055  *     else 
00056  *         printf("%s is not mapped\n", foo_get_name(f));
00057  *
00058  *     ...
00059  * 
00060  *     cp_hashtable_destroy(t);
00061  * </pre></code>
00062  * 
00063  * Note the strcmp like semantics of the compare function. The comparison
00064  * should return 0 for identical keys.
00065  * <p>
00066  * @see hash.h (util.collection) for function prototypes 
00067  * and convenience functions.
00068  * @see cp_hashtable_create, cp_hashtable_destroy, cp_hashtable_destroy_deep, cp_hashtable_put,
00069  *      cp_hashtable_get, cp_hashtable_contains, cp_hashtable_remove_deep
00070  */
00071 
00072 #include "common.h"
00073 
00074 __BEGIN_DECLS
00075 
00076 #include "collection.h"
00077 
00078 /*
00079  * cp_hashtable interface for members of mapping collections.
00080  */
00081 
00082 #include "config.h"
00083 
00084 /**
00085  * 1000000001 is a prime. HASH_SEED is used by cp_hash_string(). 
00086  */
00087 #define HASH_SEED 1000000001L
00088 
00089 #ifndef CP_HASHTABLE_DEFAULT_MIN_FILL_FACTOR
00090 #define CP_HASHTABLE_DEFAULT_MIN_FILL_FACTOR   5
00091 #endif
00092 
00093 #ifndef CP_HASHTABLE_DEFAULT_MAX_FILL_FACTOR
00094 #define CP_HASHTABLE_DEFAULT_MAX_FILL_FACTOR  70
00095 #endif
00096 
00097 /* ----------------------------------------------------------------- 
00098  * Function prototypes
00099  * ----------------------------------------------------------------- */
00100 /**
00101  * the hash function takes (void *) and returns unsigned long.
00102  *
00103  * Create a function with the name <class_name>_hash_code()
00104  */
00105 typedef unsigned long (*cp_hashfunction)(void *);
00106 
00107 
00108 /* ------------------------------------------------------------------------ 
00109  * hash function prototypes for primitives and cp_strings
00110  * ------------------------------------------------------------------------ */
00111 
00112 
00113 /**
00114  * hash function for int keys
00115  * @param key pointer to the int
00116  * @return hash code of the key
00117  */
00118 CPROPS_DLL 
00119 unsigned long cp_hash_int(void *key);
00120 
00121 
00122 /**
00123  * comparator for int keys
00124  * @param key1 pointer the first int
00125  * @param key2 pointer the second int
00126  * @retval 0 if key1 equals key2;
00127  * @retval <0 if key1 is less than key2;
00128  * @retval >0 if key1 is greater than key2
00129 
00130  */
00131 CPROPS_DLL 
00132 int cp_hash_compare_int(void *key1, void *key2);
00133 
00134 /**
00135  * hash function for long keys
00136  */
00137 CPROPS_DLL 
00138 unsigned long cp_hash_long(void *key);
00139 
00140 /**
00141  * comparator for long keys
00142  * 
00143  * @param key1 pointer the first long
00144  * @param key2 pointer the second long
00145  * @retval 0 if key1 equals key2;
00146  * @retval <0 if key1 is less than key2;
00147  * @retval >0 if key1 is greater than key2
00148  */
00149 CPROPS_DLL 
00150 int cp_hash_compare_long(void *key1, void *key2);
00151 
00152 /**
00153  * hash function for pointer keys
00154  */
00155 CPROPS_DLL 
00156 unsigned long cp_hash_addr(void *addr);
00157 
00158 /**
00159  * comparator for pointer keys
00160  * 
00161  * @param key1 pointer the first pointer
00162  * @param key2 pointer the second pointer
00163  * @retval 0 if key1 equals key2;
00164  * @retval <0 if key1 is less than key2;
00165  * @retval >0 if key1 is greater than key2
00166  */
00167 CPROPS_DLL 
00168 int cp_hash_compare_addr(void *key1, void *key2);
00169 
00170 /**
00171  * hash function for (char *) keys
00172  * @param key pointer to the cp_string
00173  * @return hash code of the key
00174  */
00175 CPROPS_DLL 
00176 unsigned long cp_hash_string(void *key);
00177 
00178 /**
00179  * case insensitive hash function for (char *) keys
00180  * @param key pointer to the cp_string
00181  * @return hash code of the key
00182  */
00183 CPROPS_DLL 
00184 unsigned long cp_hash_istring(void *key);
00185 
00186 
00187 /**
00188  * copy function for cp_string copy tables
00189  */
00190 CPROPS_DLL 
00191 void *cp_hash_copy_string(void *element);
00192 
00193 /**
00194  * comparator for (char *) keys
00195  * 
00196  * @param key1 pointer to the first cp_string
00197  * @param key2 pointer to the second cp_string
00198  * @retval 0 if key1 equals key2
00199  * @retval <>0 otherwise
00200  */
00201 CPROPS_DLL 
00202 int cp_hash_compare_string(void *key1, void *key2);
00203 
00204 
00205 /**
00206  * comparator for (char *) keys
00207  * 
00208  * @param key1 pointer to the first cp_string
00209  * @param key2 pointer to the second cp_string
00210  * @retval 0 if key1 equals key2
00211  * @retval <>0 otherwise
00212  */
00213 CPROPS_DLL 
00214 int cp_hash_compare_istring(void *key1, void *key2);
00215 
00216 
00217 
00218 /**
00219  * Internal object that implements a key, value pair plus linked list.
00220  * 
00221  * Entries which are stored under the same index in the hashtable are stored
00222  * in a linked list. The algorithm of the hashtable has to ensure that the lists
00223  * do not get too long.
00224  */
00225 typedef CPROPS_DLL struct _cp_hashtable_entry 
00226 {
00227     void *key;                   /**< key (original) needed for comparisons */
00228     void *value;                 /**< the item value being stored */
00229     unsigned long hashcode;      /**< save calculated hash-code of the key */
00230     struct _cp_hashtable_entry *next; /**< link to next entry */
00231 } cp_hashtable_entry;
00232 
00233 /**
00234  * data structure of generic synchronized cp_hashtable
00235  */
00236 typedef CPROPS_DLL struct _cp_hashtable
00237 {
00238     cp_hashtable_entry **table;     /**< array of pointers to entries */
00239     long table_size;                /**< size of the table */
00240 
00241     unsigned long items;            /**< number of items in the table */
00242     int mode;                       /**< collection mode @see collection.h */
00243     cp_hashfunction   hash_fn;      /**< pointer to hash function */
00244     cp_compare_fn     compare_fn;   /**< pointer to compare function */
00245     cp_copy_fn        copy_key;     /**< pointer to key copy function */
00246     cp_copy_fn        copy_value;   /**< pointer to value copy function */
00247         cp_destructor_fn  free_key;
00248         cp_destructor_fn  free_value;
00249 
00250     cp_lock           *lock;        /**< lock */
00251         cp_thread                 txowner;      /**< lock owner */
00252         int                               txtype;       /**< lock type */
00253 
00254         int min_size;                                   /**< table resize lower limit */
00255         int fill_factor_min;                    /**< minimal fill factor in percent */
00256         int fill_factor_max;                    /**< maximal fill factor in percent */
00257 
00258     cp_hashtable_entry **resize_table; /**< temp table for resizing */
00259     int resizing;                   /**< resize running flag */
00260     unsigned long resize_len;       /**< resize table length */
00261     cp_thread resize_thread;        /**< run resize in a separate thread  */
00262     cp_mutex *resize_lock;                      /**< for synchronizing resize operation */
00263 } cp_hashtable;
00264 
00265 
00266 /**
00267  * creates a new cp_hashtable.
00268  *
00269  * by default there is no memory management for table content; insertion, 
00270  * removal and retrieval operations are synchronized; and the table will 
00271  * automatically resize when the fill factor goes over 70% or under 5%.
00272  * @param size_hint an estimate for the initial storage requirements. The table 
00273  *
00274  * handles the storage appropriately when items become too tight. 
00275  * @param hashfn a hash code function. This should ideally produce different
00276  * results for different keys.
00277  * @param compare_fn the comparator for your key type. 
00278  * 
00279  * @return a pointer to the newly created cp_hashtable.
00280  */
00281 CPROPS_DLL 
00282 cp_hashtable *
00283         cp_hashtable_create(unsigned long size_hint, 
00284                                                 cp_hashfunction hashfn, 
00285                                                 cp_compare_fn compare_fn);
00286 
00287 /**
00288  * creates a new cp_hashtable with the specified mode.
00289  */
00290 #define cp_hashtable_create_by_mode(mode, size_hint, cp_hashfn, compare_fn) \
00291         cp_hashtable_create_by_option((mode), (size_hint), (cp_hashfn), (compare_fn), NULL, NULL, NULL, NULL)
00292 
00293 /**
00294  * creates a new cp_hashtable with COLLECTION_MODE_DEEP | COLLECTION_MODE_COPY.
00295  * @param size_hint an estimate for the initial storage requirements. The table 
00296  * handles the storage appropriately when items become too tight. 
00297  * @param hashfn a hash code function. This should ideally produce different
00298  * results for different keys.
00299  * @param compare_fn the comparator for your key type. 
00300  * 
00301  * @return a pointer to the newly created cp_hashtable.
00302  */
00303 CPROPS_DLL 
00304 cp_hashtable *
00305         cp_hashtable_create_copy_mode(unsigned long size_hint, 
00306                                                                   cp_hashfunction hash_fn, 
00307                                                                   cp_compare_fn compare_fn, 
00308                                                   cp_copy_fn copy_key, 
00309                                                                   cp_destructor_fn free_key,
00310                                                                   cp_copy_fn copy_value,
00311                                                                   cp_destructor_fn free_value);    
00312 
00313 /**
00314  * create a new table, fully specifying all parameters.
00315  * @param size_hint   initial capacity
00316  * @param hash_fn     hash function
00317  * @param compare_fn  key comparison function
00318  * @param copy_key    function to return new copies of keys
00319  * @param copy_value  function to return new copies of values
00320  * @param mode        mode flags
00321  * 
00322  * @return new created cp_hashtable. Returns NULL case of error.
00323  */
00324 CPROPS_DLL 
00325 cp_hashtable *
00326         cp_hashtable_create_by_option(int mode, unsigned long size_hint, 
00327                                                                   cp_hashfunction hash_fn, 
00328                                                                   cp_compare_fn compare_fn, 
00329                                                                   cp_copy_fn copy_key, 
00330                                                                   cp_destructor_fn free_key,
00331                                                                   cp_copy_fn copy_value,
00332                                                                   cp_destructor_fn free_value);
00333 
00334 /**
00335  * deletes a cp_hashtable according to the current mode settings
00336  * @param table        object to delete
00337  */
00338 CPROPS_DLL 
00339 void cp_hashtable_destroy(cp_hashtable *table);
00340 
00341 /**
00342  * deletes a cp_hashtable. Pointers to the keys and values are not released. Use
00343  * table if the keys and values you entered in the table should not be released
00344  * by the cp_hashtable.
00345  * @param table        object to delete
00346  */
00347 CPROPS_DLL 
00348 void cp_hashtable_destroy_shallow(cp_hashtable *table);
00349 
00350 /**
00351  * deletes a cp_hashtable. Keys and values entered in the cp_hashtable are released.
00352  * @param table        object to delete
00353  */
00354 CPROPS_DLL 
00355 void cp_hashtable_destroy_deep(cp_hashtable *table);
00356 
00357 
00358 /** 
00359  * Deep destroy with custom destructors for keys and values. NULL function 
00360  * pointers are not invoked. 
00361  */
00362 CPROPS_DLL 
00363 void cp_hashtable_destroy_custom(cp_hashtable *table, cp_destructor_fn dk, cp_destructor_fn dv);
00364 
00365 /** 
00366  * by default the get, put and remove functions as well as set and unset mode
00367  * perform their own locking. Other functions do not synchronize, since it is
00368  * assumed they would be called in a single cp_thread context - the initialization  * and deletion functions in particular. You can of course set 
00369  * COLLECTION_MODE_NOSYNC and perform your own synchronization.<p>
00370  * 
00371  * The current implementation uses a queued read/write lock where blocked
00372  * cp_threads are guaranteed to be woken by the order in which they attempted
00373  *
00374  * the following macros are defined for convenience:<p>
00375  * <ul>
00376  * <li> cp_hashtable_rdlock(table) - get a read lock on the table </li>
00377  * <li> cp_hashtable_wrlock(table) - get a write lock on the table </li>
00378  * </ul>
00379  * @param table        cp_hashtable to lock
00380  * @param type COLLECTION_LOCK_READ or COLLECTION_LOCK_WRITE
00381  */ 
00382 CPROPS_DLL 
00383 int cp_hashtable_lock(cp_hashtable *table, int type);
00384 
00385 /** unlock the table */
00386 CPROPS_DLL 
00387 int cp_hashtable_unlock(cp_hashtable *table);
00388 
00389 /** macro to get a read lock on the table
00390  */
00391 #define cp_hashtable_rdlock(table) cp_hashtable_lock((table), COLLECTION_LOCK_READ)
00392 
00393 /** macro to get a write lock on the table */
00394 #define cp_hashtable_wrlock(table) cp_hashtable_lock((table), COLLECTION_LOCK_WRITE)
00395 
00396 /**
00397  * returns the current operation mode. See cp_hashtable_set_mode for a list of
00398  * mode bits and their effects.
00399  */
00400 CPROPS_DLL 
00401 int cp_hashtable_get_mode(cp_hashtable *table);
00402 
00403 /**
00404  * set the operation mode as a bit set of the following options:
00405  * <ul>
00406  *  <li> COLLECTION_MODE_DEEP - release memory when removing references from table    </li>
00407  *  <li> COLLECTION_MODE_MULTIPLE_PUT - allow multiple values for a key    </li>
00408  *  <li> COLLECTION_MODE_COPY - keep copies rather than references    </li>
00409  *  <li> COLLECTION_MODE_NOSYNC - the table will not perform its own synchronization.    </li>
00410  *  <li> COLLECTION_MODE_NORESIZE - the table will not resize automatically.    </li>
00411  * </ul>
00412  * 
00413  * The parameter bits are flipped on. If the current mode is 
00414  * COLLECTION_MODE_DEEP and you want to change it, call
00415  * cp_hashtable_unset_mode(table, COLLECTION_MODE_DEEP).
00416  */
00417 CPROPS_DLL 
00418 int cp_hashtable_set_mode(cp_hashtable *table, int mode);
00419 
00420 
00421 /**
00422  * unset the mode bits defined by mode
00423  */
00424 CPROPS_DLL 
00425 int cp_hashtable_unset_mode(cp_hashtable *table, int mode);
00426 
00427 
00428 /**
00429  * the internal table will not be resized to less than min_size
00430  */
00431 CPROPS_DLL 
00432 int cp_hashtable_set_min_size(cp_hashtable *table, int min_size);
00433 
00434 /**
00435  * a resize is triggered when the table contains more items than
00436  * table_size * fill_factor / 100
00437  */
00438 CPROPS_DLL 
00439 int cp_hashtable_set_max_fill_factor(cp_hashtable *table, int fill_factor);
00440 
00441 /**
00442  * a resize is triggered when the table contains less items than
00443  * table_size * fill_factor / 100
00444  */
00445 CPROPS_DLL 
00446 int cp_hashtable_set_min_fill_factor(cp_hashtable *table, int fill_factor);
00447 
00448 /**
00449  * attempts to retrieve the value assigned to the key 'key'. To return
00450  * multiple values the table mode must be set to COLLECTION_MODE_MULTIPLE_VALUES, 
00451  * otherwise the only first value for the given key will be returned. 
00452  * @retval (void*)value to the value if found
00453  * @retval NULL otherwise 
00454  */
00455 CPROPS_DLL 
00456 void *cp_hashtable_get(cp_hashtable *table, void *key);
00457 
00458 /** 
00459  * retrieve the value or values for key 'key'. the 'mode' parameter sets the
00460  * mode for the current operation.
00461  */
00462 CPROPS_DLL 
00463 void *cp_hashtable_get_by_option(cp_hashtable *table, void *key, int mode);
00464 
00465 /**
00466  * Internal put method. 
00467  */
00468 CPROPS_DLL 
00469 void *cp_hashtable_put_by_option(cp_hashtable *table, void *key, void *value, int mode);
00470 
00471 /**
00472  * the key 'key' will be assigned to the value 'value'. The new value will 
00473  * override an old value if one exists. The old value will not be deallocated.
00474  * If you would need the old value to be released call cp_hashtable_put_safe instead.
00475  */
00476 CPROPS_DLL 
00477 void *cp_hashtable_put(cp_hashtable *table, void *key, void *value);
00478 
00479 /**
00480  * same as cp_hashtable_put(table, key, value) except that an old value is released if it
00481  * exists.
00482  */
00483 CPROPS_DLL 
00484 void *cp_hashtable_put_safe(cp_hashtable *table, void *key, void *value);
00485 
00486 /**
00487  * same as cp_hashtable_put(table, key, value) except that it inserts a copy
00488  * of the key and the value object.
00489  */
00490 CPROPS_DLL 
00491 void *cp_hashtable_put_copy(cp_hashtable *table, void *key, void *value);
00492 
00493 /**
00494  * Attempts to remove the mapping for key from the table.
00495  *
00496  * @param table   the object
00497  * @param key    Key to search for.
00498  * @retval value retrieved by the key (that was removed)
00499  * @retval NULL  if the table does not contain the requested key.
00500  */
00501 CPROPS_DLL 
00502 void *cp_hashtable_remove(cp_hashtable *table, void *key);
00503 
00504 /** remove all entries with current mode */
00505 CPROPS_DLL 
00506 int cp_hashtable_remove_all(cp_hashtable *table);
00507 
00508 /**
00509  * removes a mapping from the table, and deallocates the memory for the mapped
00510  * key and value.
00511  * 
00512  * @param table   the object
00513  * @param key    Key to search for.
00514  * @return 1 if the operation was successful, 0 otherwise
00515  */
00516 CPROPS_DLL 
00517 int cp_hashtable_remove_deep(cp_hashtable *table, void *key);
00518 
00519 /**
00520  * Check if there is an entry with matching key.
00521  *
00522  * @param table   the object
00523  * @param key    Key to search for.
00524  * @return 1 if table contains key, 0 otherwise
00525  */
00526 CPROPS_DLL 
00527 int cp_hashtable_contains(cp_hashtable *table, void *key);
00528 
00529 /**
00530  * get an array containing all keys mapped in table table.
00531  * @note It is the responsibility of the caller to free the returned array. 
00532  * @note The keys themselves must not be changed or deleted (read-only).
00533  */
00534 CPROPS_DLL 
00535 void **cp_hashtable_get_keys(cp_hashtable *table);
00536 
00537 /**
00538  * get an array containing all values in the table.
00539  * @note It is the responsibility of the caller to free the returned array. 
00540  * @note The values themselves must not be changed or deleted (read-only).
00541  */
00542 CPROPS_DLL 
00543 void **cp_hashtable_get_values(cp_hashtable *table);
00544 
00545 /**
00546  * Get the number of entries in the collection.
00547  * @return the number of key mappings currently in the table.
00548  */
00549 CPROPS_DLL 
00550 unsigned long cp_hashtable_count(cp_hashtable *table);
00551 
00552 /**
00553  * Check if the collection is empty.
00554  * @retval true/1 if the collection is empty
00555  * @retval false/0 if the collection has entries
00556  */
00557 #define cp_hashtable_is_empty(table) (cp_hashtable_count(table) == 0)
00558 
00559 /**
00560  * @return a prime greater than <code>size_request</code>
00561  */
00562 CPROPS_DLL 
00563 unsigned long cp_hashtable_choose_size(unsigned long size_request);
00564 
00565 __END_DECLS
00566 /** @} */
00567 #endif
00568 

Generated on Fri Oct 22 2010 11:02:22 for SST by  doxygen 1.7.1