From: Andi Gutmans Date: Wed, 19 Jan 2000 19:44:32 +0000 (+0000) Subject: - Hopefully fix the hash problem. X-Git-Tag: BEFORE_SAPIFICATION_FEB_10_2000~195 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa73f6b68f7359a30ea8068c893bcb49f1b37a49;p=php - Hopefully fix the hash problem. --- diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index c3563852a5..225e1adf0e 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -228,6 +228,10 @@ ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength } p->h = h; p->pNext = ht->arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } if (pDest) { *pDest = p->pData; } @@ -334,6 +338,10 @@ ZEND_API int zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKey } p->h = h; p->pNext = ht->arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } if (pDest) { *pDest = p->pData; } @@ -438,6 +446,10 @@ ZEND_API int zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void } p->pNext = ht->arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pInternalPointer == NULL) { ht->pInternalPointer = p; @@ -513,6 +525,10 @@ ZEND_API int zend_hash_rehash(HashTable *ht) while (p != NULL) { nIndex = p->h % ht->nTableSize; p->pNext = ht->arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } ht->arBuckets[nIndex] = p; p = p->pListNext; } @@ -542,6 +558,9 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen } else { t->pNext = p->pNext; } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } if (p->pListLast != NULL) { p->pListLast->pListNext = p->pListNext; } else { @@ -630,7 +649,6 @@ ZEND_API void zend_hash_clean(HashTable *ht) SET_INCONSISTENT(HT_OK); } -#if 0 /* This function is used by the various apply() functions. * It deletes the passed bucket, and returns the address of the * next bucket. The hash *may* be altered during that time, the @@ -639,12 +657,9 @@ ZEND_API void zend_hash_clean(HashTable *ht) static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p) { Bucket *retval; - uint nIndex; HANDLE_BLOCK_INTERRUPTIONS(); - nIndex = p->h % ht->nTableSize; - if (ht->pDestructor) { ht->pDestructor(p->pData); } @@ -653,9 +668,19 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p) } retval = p->pListNext; - if (ht->arBuckets[nIndex] == p) { + if (p->pLast) { + p->pLast->pNext = p->pNext; + } else { + uint nIndex; + + nIndex = p->h % ht->nTableSize; ht->arBuckets[nIndex] = p->pNext; } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } else { + /* Nothing to do as this list doesn't have a tail */ + } if (p->pListLast != NULL) { p->pListLast->pListNext = p->pListNext; @@ -678,24 +703,16 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p) return retval; } -#endif - ZEND_API void zend_hash_graceful_destroy(HashTable *ht) { - Bucket *p, *q; + Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - if (q->nKeyLength==0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht, q->arKey, q->nKeyLength); - } + p = zend_hash_apply_deleter(ht,p); } pefree(ht->arBuckets,ht->persistent); @@ -710,41 +727,33 @@ ZEND_API void zend_hash_graceful_destroy(HashTable *ht) ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *)) { - Bucket *p, *q; + Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - if (destruct(q->pData)) { - if (q->nKeyLength==0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht, q->arKey, q->nKeyLength); - } - } + if (destruct(p->pData)) { + p = zend_hash_apply_deleter(ht,p); + } else { + p = p->pListNext; + } } } ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument) { - Bucket *p, *q; + Bucket *p; IS_CONSISTENT(ht); p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - if (destruct(q->pData, argument)) { - if (q->nKeyLength==0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht, q->arKey, q->nKeyLength); - } + if (destruct(p->pData, argument)) { + p = zend_hash_apply_deleter(ht,p); + } else { + p = p->pListNext; } } } @@ -752,7 +761,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void *, int, va_list, zend_hash_key *), int num_args, ...) { - Bucket *p, *q; + Bucket *p; va_list args; zend_hash_key hash_key; @@ -762,17 +771,13 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht,int (*destruct)(void p = ht->pListHead; while (p != NULL) { - q = p; - p = p->pListNext; - hash_key.arKey = q->arKey; - hash_key.nKeyLength = q->nKeyLength; - hash_key.h = q->h; - if (destruct(q->pData, num_args, args, &hash_key)) { - if (q->nKeyLength==0) { - zend_hash_index_del(ht, q->h); - } else { - zend_hash_del(ht, q->arKey, q->nKeyLength); - } + hash_key.arKey = p->arKey; + hash_key.nKeyLength = p->nKeyLength; + hash_key.h = p->h; + if (destruct(p->pData, num_args, args, &hash_key)) { + p = zend_hash_apply_deleter(ht,p); + } else { + p = p->pListNext; } } @@ -788,7 +793,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyC IS_CONSISTENT(source); IS_CONSISTENT(target); - p = source->pListHead; + p = source->pListHead; while (p) { memcpy(tmp, p->pData, size); if (pCopyConstructor) { diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 95138a8a85..b824cd4bf3 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -49,6 +49,7 @@ typedef struct bucket { struct bucket *pListNext; struct bucket *pListLast; struct bucket *pNext; + struct bucket *pLast; char arKey[1]; /* Must be last element */ } Bucket;