]> granicus.if.org Git - php/commitdiff
- Make zend_hash_apply() (and friends) reentrant and much, much quicker
authorZeev Suraski <zeev@php.net>
Sun, 16 Jan 2000 20:59:03 +0000 (20:59 +0000)
committerZeev Suraski <zeev@php.net>
Sun, 16 Jan 2000 20:59:03 +0000 (20:59 +0000)
- Introduce zend_hash_graceful_destroy(), which allows the destructor functions to
  use zend_hash_apply() and/or zend_hash_graceful_destroy()
- Switch to zend_hash_graceful_destroy() in the resource list shutdowns

Zend/zend.c
Zend/zend_execute_API.c
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_list.c
Zend/zend_list.h

index de6bf93ecdc6bb353f4b39829934b5829135903c..ba07725523efe471adc8678e49afddbc06d88447 100644 (file)
@@ -283,7 +283,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals)
 static void executor_globals_dtor(zend_executor_globals *executor_globals)
 {
        zend_shutdown_constants(ELS_C);
-       destroy_resource_plist();
+       destroy_resource_plist(ELS_C);
 }
 
 
@@ -381,7 +381,7 @@ void zend_shutdown()
        zend_shutdown_extensions();
        free(zend_version_info);
 #ifndef ZTS
-       zend_shutdown_constants(ELS_C);
+       zend_shutdown_constants();
 #endif
 }
 
index fe7f7b301e53f07f7b0de206659dffe5d6fdc0c5..8e3c1fcf93a0cc086bf3060300237e86f9839a14 100644 (file)
@@ -132,7 +132,7 @@ void shutdown_executor(ELS_D)
 
        zend_hash_destroy(&EG(symbol_table));
 
-       destroy_resource_list(); /* must be destroyed after the main symbol table is destroyed */
+       destroy_resource_list(ELS_C); /* must be destroyed after the main symbol table is destroyed */
 
        zend_ptr_stack_destroy(&EG(argument_stack));
        if (EG(main_op_array)) {
index 2d2053670d21f568a499f89f7eb2ecf40d697292..db53b4ab04005bc6b5801bd4a8718eb8fb435b1e 100644 (file)
@@ -836,26 +836,82 @@ ZEND_API void zend_hash_clean(HashTable *ht)
 }
 
 
+/* 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
+ * returned value will still be valid.
+ */
+static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
+{
+       Bucket *retval;
+
+       HANDLE_BLOCK_INTERRUPTIONS();
+
+       if (!p->bIsPointer) {
+               if (ht->pDestructor) {
+                       ht->pDestructor(p->pData);
+               }
+               if (!p->pDataPtr) {
+                       pefree(p->pData, ht->persistent);
+               }
+       }
+       retval = p->pListNext;
+
+       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;
+       }
+       pefree(p,ht->persistent);
+       HANDLE_UNBLOCK_INTERRUPTIONS();
+       ht->nNumOfElements--;
+
+       return retval;
+}
+
+
+ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
+{
+       Bucket *p;
+
+       IS_CONSISTENT(ht);
+
+       p = ht->pListHead;
+       while (p != NULL) {
+               p = zend_hash_apply_deleter(ht, p);
+       }
+       pefree(ht->arBuckets,ht->persistent);
+
+       SET_INCONSISTENT(2);
+}
+
 /* This is used to selectively delete certain entries from a hashtable.
  * destruct() receives the data and decides if the entry should be deleted 
  * or not
  */
+
+
 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;
                }
        }
 }
@@ -863,20 +919,16 @@ ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *))
 
 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;
                }
        }
 }
@@ -884,7 +936,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;
 
@@ -894,17 +946,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;
                }
        }
 
index feefc731056f35957ce45e08c47f7f0195491025..60ac82d65c080b02fa0bb025d4e4ec10a0cd5d27 100644 (file)
@@ -118,6 +118,7 @@ ZEND_API int zend_hash_pointer_index_update_or_next_insert(HashTable *ht, ulong
                zend_hash_pointer_index_update_or_next_insert(ht,h,pData,HASH_UPDATE)
 #define zend_hash_next_index_pointer_insert(ht,pData) \
         zend_hash_pointer_index_update_or_next_insert(ht,0,pData,HASH_NEXT_INSERT)
+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_with_argument(HashTable *ht,int (*destruct)(void *, void *), void *);
 ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, ZEND_STD_HASH_APPLIER, int, ...);
index b154a51027e3de015076610579da4c77f76aac0e..570ceb31b032ff669d917d6a80fc13f785c5d729 100644 (file)
@@ -248,19 +248,15 @@ int init_resource_plist(ELS_D)
 }
 
 
-void destroy_resource_list(void)
+void destroy_resource_list(ELS_D)
 {
-       ELS_FETCH();
-
-       zend_hash_destroy(&EG(regular_list));
+       zend_hash_graceful_destroy(&EG(regular_list));
 }
 
 
-void destroy_resource_plist(void)
+void destroy_resource_plist(ELS_D)
 {
-       ELS_FETCH();
-
-       zend_hash_destroy(&EG(persistent_list));
+       zend_hash_graceful_destroy(&EG(persistent_list));
 }
 
 
index ac0b4038e5e5ed6a5c564d78202afb41133405d0..816b52e398ee8948a352a35b5045673bed74f556 100644 (file)
@@ -52,8 +52,8 @@ int plist_entry_destructor(void *ptr);
 int clean_module_resource_destructors(list_destructors_entry *ld, int *module_number);
 int init_resource_list(ELS_D);
 int init_resource_plist(ELS_D);
-void destroy_resource_list(void);
-void destroy_resource_plist(void);
+void destroy_resource_list(ELS_D);
+void destroy_resource_plist(ELS_D);
 
 ZEND_API int zend_list_insert(void *ptr, int type);
 ZEND_API int zend_plist_insert(void *ptr, int type);