- Hopefully fix the hash problem.

This commit is contained in:
Andi Gutmans 2000-01-19 19:44:32 +00:00
parent 2b6d84ff37
commit aa73f6b68f
2 changed files with 53 additions and 47 deletions

View file

@ -228,6 +228,10 @@ ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength
} }
p->h = h; p->h = h;
p->pNext = ht->arBuckets[nIndex]; p->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if (p->pNext) {
p->pNext->pLast = p;
}
if (pDest) { if (pDest) {
*pDest = p->pData; *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->h = h;
p->pNext = ht->arBuckets[nIndex]; p->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if (p->pNext) {
p->pNext->pLast = p;
}
if (pDest) { if (pDest) {
*pDest = p->pData; *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->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if (p->pNext) {
p->pNext->pLast = p;
}
HANDLE_BLOCK_INTERRUPTIONS(); HANDLE_BLOCK_INTERRUPTIONS();
if (ht->pInternalPointer == NULL) { if (ht->pInternalPointer == NULL) {
ht->pInternalPointer = p; ht->pInternalPointer = p;
@ -513,6 +525,10 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
while (p != NULL) { while (p != NULL) {
nIndex = p->h % ht->nTableSize; nIndex = p->h % ht->nTableSize;
p->pNext = ht->arBuckets[nIndex]; p->pNext = ht->arBuckets[nIndex];
p->pLast = NULL;
if (p->pNext) {
p->pNext->pLast = p;
}
ht->arBuckets[nIndex] = p; ht->arBuckets[nIndex] = p;
p = p->pListNext; p = p->pListNext;
} }
@ -542,6 +558,9 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
} else { } else {
t->pNext = p->pNext; t->pNext = p->pNext;
} }
if (p->pNext) {
p->pNext->pLast = p->pLast;
}
if (p->pListLast != NULL) { if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext; p->pListLast->pListNext = p->pListNext;
} else { } else {
@ -630,7 +649,6 @@ ZEND_API void zend_hash_clean(HashTable *ht)
SET_INCONSISTENT(HT_OK); SET_INCONSISTENT(HT_OK);
} }
#if 0
/* This function is used by the various apply() functions. /* This function is used by the various apply() functions.
* It deletes the passed bucket, and returns the address of the * It deletes the passed bucket, and returns the address of the
* next bucket. The hash *may* be altered during that time, 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) static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
{ {
Bucket *retval; Bucket *retval;
uint nIndex;
HANDLE_BLOCK_INTERRUPTIONS(); HANDLE_BLOCK_INTERRUPTIONS();
nIndex = p->h % ht->nTableSize;
if (ht->pDestructor) { if (ht->pDestructor) {
ht->pDestructor(p->pData); ht->pDestructor(p->pData);
} }
@ -653,9 +668,19 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
} }
retval = p->pListNext; 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; 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) { if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext; p->pListLast->pListNext = p->pListNext;
@ -678,24 +703,16 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
return retval; return retval;
} }
#endif
ZEND_API void zend_hash_graceful_destroy(HashTable *ht) ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
{ {
Bucket *p, *q; Bucket *p;
IS_CONSISTENT(ht); IS_CONSISTENT(ht);
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
q = p; p = zend_hash_apply_deleter(ht,p);
p = p->pListNext;
if (q->nKeyLength==0) {
zend_hash_index_del(ht, q->h);
} else {
zend_hash_del(ht, q->arKey, q->nKeyLength);
}
} }
pefree(ht->arBuckets,ht->persistent); 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 *)) ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *))
{ {
Bucket *p, *q; Bucket *p;
IS_CONSISTENT(ht); IS_CONSISTENT(ht);
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
q = p; if (destruct(p->pData)) {
p = p->pListNext; p = zend_hash_apply_deleter(ht,p);
if (destruct(q->pData)) { } else {
if (q->nKeyLength==0) { p = p->pListNext;
zend_hash_index_del(ht, q->h); }
} else {
zend_hash_del(ht, q->arKey, q->nKeyLength);
}
}
} }
} }
ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument) ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument)
{ {
Bucket *p, *q; Bucket *p;
IS_CONSISTENT(ht); IS_CONSISTENT(ht);
p = ht->pListHead; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
q = p; if (destruct(p->pData, argument)) {
p = p->pListNext; p = zend_hash_apply_deleter(ht,p);
if (destruct(q->pData, argument)) { } else {
if (q->nKeyLength==0) { p = p->pListNext;
zend_hash_index_del(ht, q->h);
} else {
zend_hash_del(ht, q->arKey, q->nKeyLength);
}
} }
} }
} }
@ -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, ...) 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; va_list args;
zend_hash_key hash_key; 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; p = ht->pListHead;
while (p != NULL) { while (p != NULL) {
q = p; hash_key.arKey = p->arKey;
p = p->pListNext; hash_key.nKeyLength = p->nKeyLength;
hash_key.arKey = q->arKey; hash_key.h = p->h;
hash_key.nKeyLength = q->nKeyLength; if (destruct(p->pData, num_args, args, &hash_key)) {
hash_key.h = q->h; p = zend_hash_apply_deleter(ht,p);
if (destruct(q->pData, num_args, args, &hash_key)) { } else {
if (q->nKeyLength==0) { p = p->pListNext;
zend_hash_index_del(ht, q->h);
} else {
zend_hash_del(ht, q->arKey, q->nKeyLength);
}
} }
} }
@ -788,7 +793,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyC
IS_CONSISTENT(source); IS_CONSISTENT(source);
IS_CONSISTENT(target); IS_CONSISTENT(target);
p = source->pListHead; p = source->pListHead;
while (p) { while (p) {
memcpy(tmp, p->pData, size); memcpy(tmp, p->pData, size);
if (pCopyConstructor) { if (pCopyConstructor) {

View file

@ -49,6 +49,7 @@ typedef struct bucket {
struct bucket *pListNext; struct bucket *pListNext;
struct bucket *pListLast; struct bucket *pListLast;
struct bucket *pNext; struct bucket *pNext;
struct bucket *pLast;
char arKey[1]; /* Must be last element */ char arKey[1]; /* Must be last element */
} Bucket; } Bucket;