This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A more consistent naming scheme for libiberty/hashtab.c



I really like Vlad's expandable hash tables, except that the function
names are ridiculously long and not consistent.  Also, some of the
code could do with a bit of optimization.

This patch renames all the functions to consistent, _short_ names, and
tunes the expansion and lookup functions a bit.

I don't believe there's any current code using this library.

zw

	* hashtab.c: Remove debugging variables (all_searches,
	all_collisions, all_expansions). Delete
	all_hash_table_collisions.
	(create_hash_table, delete_hash_table, empty_hash_table,
	find_hash_table_entry, remove_element_from_hash_table_entry,
	clear_hash_table_slot, traverse_hash_table, hash_table_size,
	hash_table_elements_number, hash_table_collisions): Rename to:
	htab_create, htab_delete, htab_empty, htab_find_slot,
	htab_remove_elt, htab_clear_slot, htab_traverse, htab_size,
	htab_elements, htab_collisions.
	(htab_find): New function, handles common case where you don't
	plan to add or delete an entry.
	(htab_expand): Don't create a whole new table, just a new
	entry vector.
	(htab_find_slot): Simplify logic.
	
	* hashtab.h (hash_table_t): Rename to htab_t.
	(struct hash_table): Rename to struct htab.  Shorten element
	names.  Reorder elements by size.
	(htab_hash, htab_eq, htab_trav): New typedefs for the callback
	function pointers.
	(hash_table_entry_t): Discard; just use void * for element
	type.

===================================================================
Index: libiberty/hashtab.c
--- libiberty/hashtab.c	1999/11/28 07:58:37	1.5
+++ libiberty/hashtab.c	2000/03/01 07:16:29
@@ -46,25 +46,9 @@ Boston, MA 02111-1307, USA.  */
 #include "libiberty.h"
 #include "hashtab.h"
 
-/* The following variable is used for debugging. Its value is number
-   of all calls of `find_hash_table_entry' for all hash tables. */
-
-static int all_searches = 0;
-
-/* The following variable is used for debugging. Its value is number
-   of collisions fixed for time of work with all hash tables. */
-
-static int all_collisions = 0;
-
-/* The following variable is used for debugging. Its value is number
-   of all table expansions fixed for time of work with all hash
-   tables. */
-
-static int all_expansions = 0;
-
 /* This macro defines reserved value for empty table entry. */
 
-#define EMPTY_ENTRY    NULL
+#define EMPTY_ENTRY    ((void *) 0)
 
 /* This macro defines reserved value for table entry which contained
    a deleted element. */
@@ -75,19 +59,27 @@ static int all_expansions = 0;
    greater than given source number. */
 
 static unsigned long
-higher_prime_number (number)
-     unsigned long number;
+higher_prime_number (n)
+     unsigned long n;
 {
   unsigned long i;
 
-  for (number = (number / 2) * 2 + 3;; number += 2)
+  n |= 0x01;  /* Force N to be odd.  */
+  if (n < 9)
+    return n; /* All odd numbers < 9 are prime.  */
+
+ next:
+  n += 2;
+  i = 3;
+  do
     {
-      for (i = 3; i * i <= number; i += 2)
-        if (number % i == 0)
-          break;
-      if (i * i > number)
-        return number;
+      if (n % i == 0)
+	goto next;
+      i += 2;
     }
+  while ((i * i) <= n);
+
+  return n;
 }
 
 /* This function creates table with length slightly longer than given
@@ -95,26 +87,20 @@ higher_prime_number (number)
    hash table entries are EMPTY_ENTRY).  The function returns the
    created hash table. */
 
-hash_table_t
-create_hash_table (size, hash_function, eq_function)
+htab_t
+htab_create (size, hash_f, eq_f)
      size_t size;
-     unsigned (*hash_function) PARAMS ((hash_table_entry_t));
-     int (*eq_function) PARAMS ((hash_table_entry_t, hash_table_entry_t));
+     htab_hash hash_f;
+     htab_eq eq_f;
 {
-  hash_table_t result;
+  htab_t result;
 
   size = higher_prime_number (size);
-  result = (hash_table_t) xmalloc (sizeof (*result));
-  result->entries
-    = (hash_table_entry_t *) xmalloc (size * sizeof (hash_table_entry_t));
+  result = (htab_t) xcalloc (1, sizeof (struct htab));
+  result->entries = (void **) xcalloc (size, sizeof (void *));
   result->size = size;
-  result->hash_function = hash_function;
-  result->eq_function = eq_function;
-  result->number_of_elements = 0;
-  result->number_of_deleted_elements = 0;
-  result->searches = 0;
-  result->collisions = 0;
-  memset (result->entries, 0, size * sizeof (hash_table_entry_t));
+  result->hash_f = hash_f;
+  result->eq_f = eq_f;
   return result;
 }
 
@@ -122,8 +108,8 @@ create_hash_table (size, hash_function, 
    Naturally the hash table must already exist. */
 
 void
-delete_hash_table (htab)
-     hash_table_t htab;
+htab_delete (htab)
+     htab_t htab;
 {
   free (htab->entries);
   free (htab);
@@ -132,10 +118,10 @@ delete_hash_table (htab)
 /* This function clears all entries in the given hash table.  */
 
 void
-empty_hash_table (htab)
-     hash_table_t htab;
+htab_empty (htab)
+     htab_t htab;
 {
-  memset (htab->entries, 0, htab->size * sizeof (hash_table_entry_t));
+  memset (htab->entries, 0, htab->size * sizeof (void *));
 }
 
 /* The following function changes size of memory allocated for the
@@ -145,121 +131,166 @@ empty_hash_table (htab)
    table entries is changed. */
 
 static void
-expand_hash_table (htab)
-     hash_table_t htab;
+htab_expand (htab)
+     htab_t htab;
 {
-  hash_table_t new_htab;
-  hash_table_entry_t *entry_ptr;
-  hash_table_entry_t *new_entry_ptr;
-
-  new_htab = create_hash_table (htab->number_of_elements * 2,
-                                htab->hash_function, htab->eq_function);
-  for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size;
-       entry_ptr++)
-    if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY)
-      {
-        new_entry_ptr = find_hash_table_entry (new_htab, *entry_ptr, 1);
-        *new_entry_ptr = (*entry_ptr);
-      }
-  free (htab->entries);
-  *htab = (*new_htab);
-  free (new_htab);
+  void **oentries;
+  void **olimit;
+  void **p;
+
+  oentries = htab->entries;
+  olimit = oentries + htab->size;
+
+  htab->size = higher_prime_number (htab->size * 2);
+  htab->entries = xcalloc (htab->size, sizeof (void **));
+
+  htab->n_elements -= htab->n_deleted;
+  htab->n_deleted = 0;
+
+  p = oentries;
+  do
+    {
+      void *x = *p;
+      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
+	{
+	  void **q = htab_find_slot (htab, x, 1);
+	  *q = x;
+	}
+      p++;
+    }
+  while (p < olimit);
+  free (oentries);
 }
 
-/* This function searches for hash table entry which contains element
-   equal to given value or empty entry in which given value can be
-   placed (if the element with given value does not exist in the
-   table).  The function works in two regimes.  The first regime is
-   used only for search.  The second is used for search and
-   reservation empty entry for given value.  The table is expanded if
-   occupancy (taking into accout also deleted elements) is more than
-   75%.  Naturally the hash table must already exist.  If reservation
-   flag is TRUE then the element with given value should be inserted
-   into the table entry before another call of
-   `find_hash_table_entry'. */
-
-hash_table_entry_t *
-find_hash_table_entry (htab, element, reserve)
-     hash_table_t htab;
-     hash_table_entry_t element;
-     int reserve;
-{
-  hash_table_entry_t *entry_ptr;
-  hash_table_entry_t *first_deleted_entry_ptr;
-  unsigned index, hash_value, secondary_hash_value;
+/* This function searches for a hash table entry equal to the given
+   element.  It cannot be used to insert or delete an element.  */
 
-  if (htab->size * 3 <= htab->number_of_elements * 4)
+void *
+htab_find (htab, element)
+     htab_t htab;
+     const void *element;
+{
+  unsigned int index, hash, hash2;
+  size_t size;
+
+  htab->searches++;
+  size = htab->size;
+  hash = (*htab->hash_f) (element);
+  hash2 = 1 + hash % (size - 2);
+  index = hash % size;
+
+  for (;;)
     {
-      all_expansions++;
-      expand_hash_table (htab);
+      void *entry = htab->entries[index];
+      if (entry == EMPTY_ENTRY)
+	return NULL;
+      else if (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))
+	return entry;
+
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+	index -= size;
     }
-  hash_value = (*htab->hash_function) (element);
-  secondary_hash_value = 1 + hash_value % (htab->size - 2);
-  index = hash_value % htab->size;
+}
+
+/* This function searches for a hash table slot containing an entry
+   equal to the given element.  To delete an entry, call this with
+   INSERT = 0, then call htab_clear_slot on the slot returned (possibly
+   after doing some checks).  To insert an entry, call this with
+   INSERT = 1, then write the value you want into the returned slot.  */
+
+void **
+htab_find_slot (htab, element, insert)
+     htab_t htab;
+     const void *element;
+     int insert;
+{
+  void **first_deleted_slot;
+  unsigned int index, hash, hash2;
+  size_t size;
+
+  if (insert && htab->size * 3 <= htab->n_elements * 4)
+    htab_expand (htab);
+
+  size = htab->size;
+  hash = (*htab->hash_f) (element);
+  hash2 = 1 + hash % (size - 2);
+  index = hash % size;
+
   htab->searches++;
-  all_searches++;
-  first_deleted_entry_ptr = NULL;
-  for (;;htab->collisions++, all_collisions++)
+  first_deleted_slot = NULL;
+
+  for (;;)
     {
-      entry_ptr = htab->entries + index;
-      if (*entry_ptr == EMPTY_ENTRY)
-        {
-          if (reserve)
+      void *entry = htab->entries[index];
+      if (entry == EMPTY_ENTRY)
+	{
+	  if (!insert)
+	    return NULL;
+
+	  htab->n_elements++;
+
+	  if (first_deleted_slot)
 	    {
-	      htab->number_of_elements++;
-	      if (first_deleted_entry_ptr != NULL)
-		{
-		  entry_ptr = first_deleted_entry_ptr;
-		  *entry_ptr = EMPTY_ENTRY;
-		}
+	      *first_deleted_slot = EMPTY_ENTRY;
+	      return first_deleted_slot;
 	    }
-          break;
-        }
-      else if (*entry_ptr != DELETED_ENTRY)
-        {
-          if ((*htab->eq_function) (*entry_ptr, element))
-            break;
-        }
-      else if (first_deleted_entry_ptr == NULL)
-	first_deleted_entry_ptr = entry_ptr;
-      index += secondary_hash_value;
-      if (index >= htab->size)
-        index -= htab->size;
+
+	  return &htab->entries[index];
+	}
+
+      if (entry == DELETED_ENTRY)
+	{
+	  if (!first_deleted_slot)
+	    first_deleted_slot = &htab->entries[index];
+	}
+      else
+	{
+	  if ((*htab->eq_f) (entry, element))
+	    return &htab->entries[index];
+	}
+      
+      htab->collisions++;
+      index += hash2;
+      if (index >= size)
+	index -= size;
     }
-  return entry_ptr;
 }
 
-/* This function deletes element with given value from hash table.
-   The hash table entry value will be `DELETED_ENTRY' after the
-   function call.  Naturally the hash table must already exist.  Hash
-   table entry for given value should be not empty (or deleted). */
+/* This function deletes an element with the given value from hash
+   table.  If there is no matching element in the hash table, this
+   function does nothing.  */
 
 void
-remove_element_from_hash_table_entry (htab, element)
-     hash_table_t htab;
-     hash_table_entry_t element;
-{
-  hash_table_entry_t *entry_ptr;
+htab_remove_elt (htab, element)
+     htab_t htab;
+     void *element;
+{
+  void **slot;
+
+  slot = htab_find_slot (htab, element, 0);
+  if (*slot == EMPTY_ENTRY)
+    return;
 
-  entry_ptr = find_hash_table_entry (htab, element, 0);
-  *entry_ptr = DELETED_ENTRY;
-  htab->number_of_deleted_elements++;
+  *slot = DELETED_ENTRY;
+  htab->n_deleted++;
 }
 
-/* This function clears a specified slot in a hash table.
-   It is useful when you've already done the lookup and don't want to
-   do it again.  */
+/* This function clears a specified slot in a hash table.  It is
+   useful when you've already done the lookup and don't want to do it
+   again.  */
 
 void
-clear_hash_table_slot (htab, slot)
-     hash_table_t htab;
-     hash_table_entry_t *slot;
+htab_clear_slot (htab, slot)
+     htab_t htab;
+     void **slot;
 {
   if (slot < htab->entries || slot >= htab->entries + htab->size
       || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY)
     abort ();
   *slot = DELETED_ENTRY;
-  htab->number_of_deleted_elements++;
+  htab->n_deleted++;
 }
 
 /* This function scans over the entire hash table calling
@@ -268,24 +299,29 @@ clear_hash_table_slot (htab, slot)
    argument.  */
 
 void
-traverse_hash_table (htab, callback, info)
-     hash_table_t htab;
-     int (*callback) PARAMS ((hash_table_entry_t, void *));
+htab_traverse (htab, callback, info)
+     htab_t htab;
+     htab_trav callback;
      void *info;
 {
-  hash_table_entry_t *entry_ptr;
-  for (entry_ptr = htab->entries; entry_ptr < htab->entries + htab->size;
-       entry_ptr++)
-    if (*entry_ptr != EMPTY_ENTRY && *entry_ptr != DELETED_ENTRY)
-      if (!callback (*entry_ptr, info))
-	break;
+  void **slot, **limit;
+  slot = htab->entries;
+  limit = slot + htab->size;
+  do
+    {
+      void *x = *slot;
+      if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
+	if (!(*callback) (x, info))
+	  break;
+    }
+  while (++slot < limit);
 }
 
 /* The following function returns current size of given hash table. */
 
 size_t
-hash_table_size (htab)
-     hash_table_t htab;
+htab_size (htab)
+     htab_t htab;
 {
   return htab->size;
 }
@@ -294,37 +330,23 @@ hash_table_size (htab)
    hash table. */
 
 size_t
-hash_table_elements_number (htab)
-     hash_table_t htab;
+htab_elements (htab)
+     htab_t htab;
 {
-  return htab->number_of_elements - htab->number_of_deleted_elements;
+  return htab->n_elements - htab->n_deleted;
 }
 
 /* The following function returns number of percents of fixed
    collisions during all work with given hash table. */
 
-int
-hash_table_collisions (htab)
-     hash_table_t htab;
+double
+htab_collisions (htab)
+     htab_t htab;
 {
   int searches;
 
   searches = htab->searches;
-  if (searches == 0)
-    searches++;
-  return htab->collisions * 100 / searches;
-}
-
-/* The following function returns number of percents of fixed
-   collisions during all work with all hash tables. */
-
-int
-all_hash_table_collisions ()
-{
-  int searches;
-
-  searches = all_searches;
   if (searches == 0)
-    searches++;
-  return all_collisions * 100 / searches;
+    return 0.0;
+  return (double)htab->collisions / (double)searches;
 }
===================================================================
Index: include/hashtab.h
--- include/hashtab.h	1999/10/23 15:56:52	1.2
+++ include/hashtab.h	2000/03/01 07:16:29
@@ -38,69 +38,72 @@ extern "C" {
 
 #include <ansidecl.h>
 
-/* The hash table element is represented by the following type. */
+/* Callback function pointer types.  */
 
-typedef const void *hash_table_entry_t;
+/* Calculate hash of a table entry.  */
+typedef unsigned int (*htab_hash) PARAMS ((const void *));
 
+/* Compare a table entry with a possible entry.  The entry already in
+   the table always comes first.  */
+typedef int (*htab_eq) PARAMS ((const void *, const void *));
+
+/* Function called by htab_traverse for each live element.  The first
+   arg is the element, the second arg is the auxiliary pointer handed
+   to htab_traverse.  Return 1 to continue scan, 0 to stop.  */
+typedef int (*htab_trav) PARAMS ((void *, void *));
+
 /* Hash tables are of the following type.  The structure
    (implementation) of this type is not needed for using the hash
    tables.  All work with hash table should be executed only through
    functions mentioned below. */
 
-typedef struct hash_table
+struct htab
 {
+  /* Pointer to hash function.  */
+  htab_hash hash_f;
+
+  /* Pointer to comparison function. */
+  htab_eq eq_f;
+
+  /* Table itself */
+  void **entries;
+
   /* Current size (in entries) of the hash table */
   size_t size;
+
   /* Current number of elements including also deleted elements */
-  size_t number_of_elements;
+  size_t n_elements;
+
   /* Current number of deleted elements in the table */
-  size_t number_of_deleted_elements;
+  size_t n_deleted;
+
   /* The following member is used for debugging. Its value is number
-     of all calls of `find_hash_table_entry' for the hash table. */
-  int searches;
+     of all calls of `htab_find_slot' for the hash table. */
+  unsigned int searches;
+
   /* The following member is used for debugging.  Its value is number
      of collisions fixed for time of work with the hash table. */
-  int collisions;
-  /* Pointer to function for evaluation of hash value (any unsigned value).
-     This function has one parameter of type hash_table_entry_t. */
-  unsigned (*hash_function) PARAMS ((hash_table_entry_t));
-  /* Pointer to function for test on equality of hash table elements (two
-     parameter of type hash_table_entry_t. */
-  int (*eq_function) PARAMS ((hash_table_entry_t, hash_table_entry_t));
-  /* Table itself */
-  hash_table_entry_t *entries;
-} *hash_table_t;
+  unsigned int collisions;
+};
 
+typedef struct htab *htab_t;
 
 /* The prototypes of the package functions. */
-
-extern hash_table_t create_hash_table
-  PARAMS ((size_t, unsigned (*) (hash_table_entry_t),
-	   int (*) (hash_table_entry_t, hash_table_entry_t)));
-
-extern void delete_hash_table PARAMS ((hash_table_t));
-
-extern void empty_hash_table PARAMS ((hash_table_t));
-
-extern hash_table_entry_t *find_hash_table_entry
-  PARAMS ((hash_table_t, hash_table_entry_t, int));
-
-extern void remove_element_from_hash_table_entry PARAMS ((hash_table_t,
-							  hash_table_entry_t));
-
-extern void clear_hash_table_slot PARAMS ((hash_table_t, hash_table_entry_t *));
-
-extern void traverse_hash_table PARAMS ((hash_table_t,
-					 int (*) (hash_table_entry_t, void *),
-					 void *));
-    
-extern size_t hash_table_size PARAMS ((hash_table_t));
-
-extern size_t hash_table_elements_number PARAMS ((hash_table_t));
-
-extern int hash_table_collisions PARAMS ((hash_table_t));
 
-extern int all_hash_table_collisions PARAMS ((void));
+extern htab_t	htab_create	PARAMS ((size_t, htab_hash, htab_eq));
+extern void	htab_delete	PARAMS ((htab_t));
+extern void	htab_empty	PARAMS ((htab_t));
+
+extern void    *htab_find	PARAMS ((htab_t, const void *));
+extern void   **htab_find_slot	PARAMS ((htab_t, const void *, int));
+extern void	htab_clear_slot	PARAMS ((htab_t, void **));
+extern void	htab_remove_elt	PARAMS ((htab_t, void *));
+
+extern void	htab_traverse	PARAMS ((htab_t, htab_trav, void *));
+
+extern size_t	htab_size	PARAMS ((htab_t));
+extern size_t	htab_elements	PARAMS ((htab_t));
+extern double	htab_collisions	PARAMS ((htab_t));
 
 #ifdef __cplusplus
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]