diff src/hashtable.c @ 237:73354c21f1e4 v7.0066

updated for version 7.0066
author vimboss
date Fri, 15 Apr 2005 21:13:42 +0000
parents 1a145815483e
children a711f7a6852d
line wrap: on
line diff
--- a/src/hashtable.c
+++ b/src/hashtable.c
@@ -38,9 +38,9 @@
 /* Magic value for algorithm that walks through the array. */
 #define PERTURB_SHIFT 5
 
-static int hash_may_resize __ARGS((hashtab_T *ht));
+static int hash_may_resize __ARGS((hashtab_T *ht, int minitems));
 
-#if 0  /* not used */
+#if defined(FEAT_SYN_HL) || defined(PROTO)
 /*
  * Create an empty hash table.
  * Returns NULL when out of memory.
@@ -189,7 +189,7 @@ hash_add_item(ht, hi, key, hash)
     hash_T	hash;
 {
     /* If resizing failed before and it fails again we can't add an item. */
-    if (ht->ht_error && hash_may_resize(ht) == FAIL)
+    if (ht->ht_error && hash_may_resize(ht, 0) == FAIL)
 	return FAIL;
 
     ++ht->ht_used;
@@ -199,7 +199,7 @@ hash_add_item(ht, hi, key, hash)
     hi->hi_hash = hash;
 
     /* When the space gets low may resize the array. */
-    return hash_may_resize(ht);
+    return hash_may_resize(ht, 0);
 }
 
 #if 0  /* not used */
@@ -233,7 +233,7 @@ hash_remove(ht, hi)
 {
     --ht->ht_used;
     hi->hi_key = HI_KEY_REMOVED;
-    hash_may_resize(ht);
+    hash_may_resize(ht, 0);
 }
 
 /*
@@ -249,6 +249,20 @@ hash_lock(ht)
 }
 
 /*
+ * Lock a hashtable at the specified number of entries.
+ * Caller must make sure no more than "size" entries will be added.
+ * Must call hash_unlock() later.
+ */
+    void
+hash_lock_size(ht, size)
+    hashtab_T	*ht;
+    int		size;
+{
+    (void)hash_may_resize(ht, size);
+    ++ht->ht_locked;
+}
+
+/*
  * Unlock a hashtable: allow ht_array changes again.
  * Table will be resized (shrink) when necessary.
  * This must balance a call to hash_lock().
@@ -258,7 +272,7 @@ hash_unlock(ht)
     hashtab_T	*ht;
 {
     --ht->ht_locked;
-    (void)hash_may_resize(ht);
+    (void)hash_may_resize(ht, 0);
 }
 
 /*
@@ -267,8 +281,9 @@ hash_unlock(ht)
  * Returns OK or FAIL (out of memory).
  */
     static int
-hash_may_resize(ht)
+hash_may_resize(ht, minitems)
     hashtab_T	*ht;
+    int		minitems;		/* minimal number of items */
 {
     hashitem_T	temparray[HT_INIT_SIZE];
     hashitem_T	*oldarray, *newarray;
@@ -291,25 +306,37 @@ hash_may_resize(ht)
 	EMSG("hash_may_resize(): table completely filled");
 #endif
 
-    /* Return quickly for small tables with at least two NULL items.  NULL
-     * items are required for the lookup to decide a key isn't there. */
-    if (ht->ht_filled < HT_INIT_SIZE - 1 && ht->ht_array == ht->ht_smallarray)
-	return OK;
+    if (minitems == 0)
+    {
+	/* Return quickly for small tables with at least two NULL items.  NULL
+	 * items are required for the lookup to decide a key isn't there. */
+	if (ht->ht_filled < HT_INIT_SIZE - 1
+					 && ht->ht_array == ht->ht_smallarray)
+	    return OK;
 
-    /*
-     * Grow or refill the array when it's more than 2/3 full (including
-     * removed items, so that they get cleaned up).
-     * Shrink the array when it's less than 1/5 full.  When growing it is at
-     * least 1/4 full (avoids repeated grow-shrink operations)
-     */
-    oldsize = ht->ht_mask + 1;
-    if (ht->ht_filled * 3 < oldsize * 2 && ht->ht_used > oldsize / 5)
-	return OK;
+	/*
+	 * Grow or refill the array when it's more than 2/3 full (including
+	 * removed items, so that they get cleaned up).
+	 * Shrink the array when it's less than 1/5 full.  When growing it is
+	 * at least 1/4 full (avoids repeated grow-shrink operations)
+	 */
+	oldsize = ht->ht_mask + 1;
+	if (ht->ht_filled * 3 < oldsize * 2 && ht->ht_used > oldsize / 5)
+	    return OK;
 
-    if (ht->ht_used > 1000)
-	minsize = ht->ht_used * 2;  /* it's big, don't make too much room */
+	if (ht->ht_used > 1000)
+	    minsize = ht->ht_used * 2;  /* it's big, don't make too much room */
+	else
+	    minsize = ht->ht_used * 4;  /* make plenty of room */
+    }
     else
-	minsize = ht->ht_used * 4;  /* make plenty of room */
+    {
+	/* Use specified size. */
+	if (minitems < ht->ht_used)	/* just in case... */
+	    minitems = ht->ht_used;
+	minsize = minitems * 3 / 2;	/* array is up to 2/3 full */
+    }
+
     newsize = HT_INIT_SIZE;
     while (newsize < minsize)
     {