]> granicus.if.org Git - php/commitdiff
Rename+move zend_hash_apply_deleter and reuse it
authorNikita Popov <nikic@php.net>
Thu, 20 Mar 2014 22:50:04 +0000 (23:50 +0100)
committerNikita Popov <nikic@php.net>
Thu, 20 Mar 2014 23:14:52 +0000 (00:14 +0100)
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.

Zend/zend_hash.c

index ab8601c2ebe22b4f663d2fab52f7321a85d4d4fd..aa3587c67596792d01b0d9f1fd09d78faca1b83d 100644 (file)
@@ -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;
                }