mirror of
https://github.com/php/php-src.git
synced 2024-12-12 19:33:31 +08:00
Rename+move zend_hash_apply_deleter and reuse it
The interruption handling was normalized to wrap the entire deletion operation (instead of leaving out the destructor call and/or the deallocation) per the recommendation of somebody (don't remember who) familiar with zend signals. There is an always-inlined variant of the function for use in the main deletion function, to ensure there is no performance impact.
This commit is contained in:
parent
4efa58dd59
commit
4e7e301dda
212
Zend/zend_hash.c
212
Zend/zend_hash.c
@ -156,6 +156,51 @@ static inline void zend_hash_bucket_update(
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void i_zend_hash_bucket_delete(HashTable *ht, Bucket *p)
|
||||
{
|
||||
#ifdef ZEND_SIGNALS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
if (p->pLast) {
|
||||
p->pLast->pNext = p->pNext;
|
||||
} else {
|
||||
ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
|
||||
}
|
||||
if (p->pNext) {
|
||||
p->pNext->pLast = p->pLast;
|
||||
}
|
||||
if (p->pListLast != NULL) {
|
||||
p->pListLast->pListNext = p->pListNext;
|
||||
} else {
|
||||
/* Deleting the head of the list */
|
||||
ht->pListHead = p->pListNext;
|
||||
}
|
||||
if (p->pListNext != NULL) {
|
||||
p->pListNext->pListLast = p->pListLast;
|
||||
} else {
|
||||
/* Deleting the tail of the list */
|
||||
ht->pListTail = p->pListLast;
|
||||
}
|
||||
if (ht->pInternalPointer == p) {
|
||||
ht->pInternalPointer = p->pListNext;
|
||||
}
|
||||
ht->nNumOfElements--;
|
||||
if (ht->pDestructor) {
|
||||
ht->pDestructor(p->pData);
|
||||
}
|
||||
if (p->pData != &p->pDataPtr) {
|
||||
pefree(p->pData, ht->persistent);
|
||||
}
|
||||
pefree(p, ht->persistent);
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
}
|
||||
|
||||
static void zend_hash_bucket_delete(HashTable *ht, Bucket *p) {
|
||||
i_zend_hash_bucket_delete(ht, p);
|
||||
}
|
||||
|
||||
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
|
||||
{
|
||||
uint i = 3;
|
||||
@ -427,9 +472,6 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n
|
||||
{
|
||||
uint nIndex;
|
||||
Bucket *p;
|
||||
#ifdef ZEND_SIGNALS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
IS_CONSISTENT(ht);
|
||||
|
||||
@ -444,38 +486,7 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint n
|
||||
&& (p->nKeyLength == nKeyLength)
|
||||
&& ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */
|
||||
|| !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
if (p == ht->arBuckets[nIndex]) {
|
||||
ht->arBuckets[nIndex] = p->pNext;
|
||||
} else {
|
||||
p->pLast->pNext = p->pNext;
|
||||
}
|
||||
if (p->pNext) {
|
||||
p->pNext->pLast = p->pLast;
|
||||
}
|
||||
if (p->pListLast != NULL) {
|
||||
p->pListLast->pListNext = p->pListNext;
|
||||
} else {
|
||||
/* Deleting the head of the list */
|
||||
ht->pListHead = p->pListNext;
|
||||
}
|
||||
if (p->pListNext != NULL) {
|
||||
p->pListNext->pListLast = p->pListLast;
|
||||
} else {
|
||||
ht->pListTail = p->pListLast;
|
||||
}
|
||||
if (ht->pInternalPointer == p) {
|
||||
ht->pInternalPointer = p->pListNext;
|
||||
}
|
||||
ht->nNumOfElements--;
|
||||
if (ht->pDestructor) {
|
||||
ht->pDestructor(p->pData);
|
||||
}
|
||||
if (p->pData != &p->pDataPtr) {
|
||||
pefree(p->pData, ht->persistent);
|
||||
}
|
||||
pefree(p, ht->persistent);
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
i_zend_hash_bucket_delete(ht, p);
|
||||
return SUCCESS;
|
||||
}
|
||||
p = p->pNext;
|
||||
@ -542,63 +553,12 @@ ZEND_API void zend_hash_clean(HashTable *ht)
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is used by the various apply() functions.
|
||||
* It deletes the passed bucket.
|
||||
*/
|
||||
static void zend_hash_apply_deleter(HashTable *ht, Bucket *p)
|
||||
{
|
||||
#ifdef ZEND_SIGNALS
|
||||
TSRMLS_FETCH();
|
||||
#endif
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
if (p->pLast) {
|
||||
p->pLast->pNext = p->pNext;
|
||||
} else {
|
||||
uint nIndex;
|
||||
|
||||
nIndex = p->h & ht->nTableMask;
|
||||
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;
|
||||
} else {
|
||||
/* Deleting the head of the list */
|
||||
ht->pListHead = p->pListNext;
|
||||
}
|
||||
if (p->pListNext != NULL) {
|
||||
p->pListNext->pListLast = p->pListLast;
|
||||
} else {
|
||||
ht->pListTail = p->pListLast;
|
||||
}
|
||||
if (ht->pInternalPointer == p) {
|
||||
ht->pInternalPointer = p->pListNext;
|
||||
}
|
||||
ht->nNumOfElements--;
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
if (ht->pDestructor) {
|
||||
ht->pDestructor(p->pData);
|
||||
}
|
||||
if (p->pData != &p->pDataPtr) {
|
||||
pefree(p->pData, ht->persistent);
|
||||
}
|
||||
pefree(p, ht->persistent);
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
|
||||
{
|
||||
IS_CONSISTENT(ht);
|
||||
|
||||
while (ht->pListHead != NULL) {
|
||||
zend_hash_apply_deleter(ht, ht->pListHead);
|
||||
zend_hash_bucket_delete(ht, ht->pListHead);
|
||||
}
|
||||
|
||||
if (ht->nTableMask) {
|
||||
@ -613,7 +573,7 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
|
||||
IS_CONSISTENT(ht);
|
||||
|
||||
while (ht->pListTail != NULL) {
|
||||
zend_hash_apply_deleter(ht, ht->pListTail);
|
||||
zend_hash_bucket_delete(ht, ht->pListTail);
|
||||
}
|
||||
|
||||
if (ht->nTableMask) {
|
||||
@ -645,7 +605,7 @@ ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
|
||||
|
||||
Bucket *p_next = p->pListNext;
|
||||
if (result & ZEND_HASH_APPLY_REMOVE) {
|
||||
zend_hash_apply_deleter(ht, p);
|
||||
zend_hash_bucket_delete(ht, p);
|
||||
}
|
||||
p = p_next;
|
||||
|
||||
@ -670,7 +630,7 @@ ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t appl
|
||||
|
||||
Bucket *p_next = p->pListNext;
|
||||
if (result & ZEND_HASH_APPLY_REMOVE) {
|
||||
zend_hash_apply_deleter(ht, p);
|
||||
zend_hash_bucket_delete(ht, p);
|
||||
}
|
||||
p = p_next;
|
||||
|
||||
@ -703,7 +663,7 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func
|
||||
|
||||
Bucket *p_next = p->pListNext;
|
||||
if (result & ZEND_HASH_APPLY_REMOVE) {
|
||||
zend_hash_apply_deleter(ht, p);
|
||||
zend_hash_bucket_delete(ht, p);
|
||||
}
|
||||
p = p_next;
|
||||
|
||||
@ -731,7 +691,7 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
|
||||
|
||||
Bucket *p_last = p->pListLast;
|
||||
if (result & ZEND_HASH_APPLY_REMOVE) {
|
||||
zend_hash_apply_deleter(ht, p);
|
||||
zend_hash_bucket_delete(ht, p);
|
||||
}
|
||||
p = p_last;
|
||||
|
||||
@ -1204,8 +1164,6 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
if (q) {
|
||||
if (mode != HASH_UPDATE_KEY_ANYWAY) {
|
||||
Bucket *r = p->pListLast;
|
||||
@ -1220,73 +1178,17 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const
|
||||
}
|
||||
if (mode & found) {
|
||||
/* delete current bucket */
|
||||
if (p == ht->arBuckets[p->h & ht->nTableMask]) {
|
||||
ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
|
||||
} else {
|
||||
p->pLast->pNext = p->pNext;
|
||||
}
|
||||
if (p->pNext) {
|
||||
p->pNext->pLast = p->pLast;
|
||||
}
|
||||
if (p->pListLast != NULL) {
|
||||
p->pListLast->pListNext = p->pListNext;
|
||||
} else {
|
||||
/* Deleting the head of the list */
|
||||
ht->pListHead = p->pListNext;
|
||||
}
|
||||
if (p->pListNext != NULL) {
|
||||
p->pListNext->pListLast = p->pListLast;
|
||||
} else {
|
||||
ht->pListTail = p->pListLast;
|
||||
}
|
||||
if (ht->pInternalPointer == p) {
|
||||
ht->pInternalPointer = p->pListNext;
|
||||
}
|
||||
ht->nNumOfElements--;
|
||||
if (ht->pDestructor) {
|
||||
ht->pDestructor(p->pData);
|
||||
}
|
||||
if (p->pData != &p->pDataPtr) {
|
||||
pefree(p->pData, ht->persistent);
|
||||
}
|
||||
pefree(p, ht->persistent);
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
zend_hash_bucket_delete(ht, p);
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* delete another bucket with the same key */
|
||||
if (q == ht->arBuckets[q->h & ht->nTableMask]) {
|
||||
ht->arBuckets[q->h & ht->nTableMask] = q->pNext;
|
||||
} else {
|
||||
q->pLast->pNext = q->pNext;
|
||||
}
|
||||
if (q->pNext) {
|
||||
q->pNext->pLast = q->pLast;
|
||||
}
|
||||
if (q->pListLast != NULL) {
|
||||
q->pListLast->pListNext = q->pListNext;
|
||||
} else {
|
||||
/* Deleting the head of the list */
|
||||
ht->pListHead = q->pListNext;
|
||||
}
|
||||
if (q->pListNext != NULL) {
|
||||
q->pListNext->pListLast = q->pListLast;
|
||||
} else {
|
||||
ht->pListTail = q->pListLast;
|
||||
}
|
||||
if (ht->pInternalPointer == q) {
|
||||
ht->pInternalPointer = q->pListNext;
|
||||
}
|
||||
ht->nNumOfElements--;
|
||||
if (ht->pDestructor) {
|
||||
ht->pDestructor(q->pData);
|
||||
}
|
||||
if (q->pData != &q->pDataPtr) {
|
||||
pefree(q->pData, ht->persistent);
|
||||
}
|
||||
pefree(q, ht->persistent);
|
||||
zend_hash_bucket_delete(ht, q);
|
||||
}
|
||||
|
||||
HANDLE_BLOCK_INTERRUPTIONS();
|
||||
|
||||
if (p->pNext) {
|
||||
p->pNext->pLast = p->pLast;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user