zend_weakrefs: Add zend_weakrefs_hash_(clean|destroy)() (#16439)

These are equivalent to `zend_hash_clean()` and `zend_hash_destroy()`
respectively, but take care of correctly unregistering the weak references to
the keys.

This addition rounds off the weakmap functionality added in
471102edcd by taking one possible footgun away
from the user.
This commit is contained in:
Tim Düsterhus 2024-10-14 18:57:08 +02:00 committed by GitHub
parent 6292e5c878
commit 3401d55726
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 14 additions and 5 deletions

View File

@ -183,6 +183,13 @@ ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key) {
return FAILURE;
}
ZEND_API void zend_weakrefs_hash_clean(HashTable *ht) {
zend_ulong obj_key;
ZEND_HASH_FOREACH_NUM_KEY(ht, obj_key) {
zend_weakrefs_hash_del(ht, zend_weakref_key_to_object(obj_key));
} ZEND_HASH_FOREACH_END();
}
void zend_weakrefs_init(void) {
zend_hash_init(&EG(weakrefs), 8, NULL, NULL, 0);
}

View File

@ -41,6 +41,12 @@ static zend_always_inline void *zend_weakrefs_hash_add_ptr(HashTable *ht, zend_o
return NULL;
}
}
ZEND_API void zend_weakrefs_hash_clean(HashTable *ht);
static zend_always_inline void zend_weakrefs_hash_destroy(HashTable *ht) {
zend_weakrefs_hash_clean(ht);
ZEND_ASSERT(zend_hash_num_elements(ht) == 0);
zend_hash_destroy(ht);
}
/* Because php uses the raw numbers as a hash function, raw pointers will lead to hash collisions.
* We have a guarantee that the lowest ZEND_MM_ALIGNED_OFFSET_LOG2 bits of a pointer are zero.

View File

@ -1354,11 +1354,7 @@ PHP_RINIT_FUNCTION(zend_test)
PHP_RSHUTDOWN_FUNCTION(zend_test)
{
zend_ulong obj_key;
ZEND_HASH_FOREACH_NUM_KEY(&ZT_G(global_weakmap), obj_key) {
zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
} ZEND_HASH_FOREACH_END();
zend_hash_destroy(&ZT_G(global_weakmap));
zend_weakrefs_hash_destroy(&ZT_G(global_weakmap));
if (ZT_G(zend_test_heap)) {
free(ZT_G(zend_test_heap));