mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Add ZEND_API for weakmap functionality via zend_weakrefs_hash_add/del
Closes GH-7600.
This commit is contained in:
parent
decf906a90
commit
471102edcd
6 changed files with 151 additions and 6 deletions
|
@ -63,8 +63,7 @@ static inline void zend_weakref_unref_single(
|
|||
wr->referent = NULL;
|
||||
} else {
|
||||
ZEND_ASSERT(tag == ZEND_WEAKREF_TAG_MAP);
|
||||
zend_weakmap *wm = ptr;
|
||||
zend_hash_index_del(&wm->ht, obj_addr);
|
||||
zend_hash_index_del((HashTable *) ptr, obj_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,6 +143,23 @@ static void zend_weakref_unregister(zend_object *object, void *payload) {
|
|||
ZEND_WEAKREF_GET_PTR(payload), ZEND_WEAKREF_GET_TAG(payload), obj_addr);
|
||||
}
|
||||
|
||||
ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pData) {
|
||||
zval *zv = zend_hash_index_add(ht, (zend_ulong) key, pData);
|
||||
if (zv) {
|
||||
zend_weakref_register(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP));
|
||||
}
|
||||
return zv;
|
||||
}
|
||||
|
||||
ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key) {
|
||||
zval *zv = zend_hash_index_find(ht, (zend_ulong) key);
|
||||
if (zv) {
|
||||
zend_weakref_unregister(key, ZEND_WEAKREF_ENCODE(ht, ZEND_WEAKREF_TAG_MAP));
|
||||
return SUCCESS;
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
void zend_weakrefs_init(void) {
|
||||
zend_hash_init(&EG(weakrefs), 8, NULL, NULL, 0);
|
||||
}
|
||||
|
@ -281,7 +297,7 @@ static void zend_weakmap_free_obj(zend_object *object)
|
|||
zend_ulong obj_addr;
|
||||
ZEND_HASH_FOREACH_NUM_KEY(&wm->ht, obj_addr) {
|
||||
zend_weakref_unregister(
|
||||
(zend_object *) obj_addr, ZEND_WEAKREF_ENCODE(wm, ZEND_WEAKREF_TAG_MAP));
|
||||
(zend_object *) obj_addr, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP));
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
zend_hash_destroy(&wm->ht);
|
||||
zend_object_std_dtor(&wm->std);
|
||||
|
@ -340,7 +356,7 @@ static void zend_weakmap_write_dimension(zend_object *object, zval *offset, zval
|
|||
return;
|
||||
}
|
||||
|
||||
zend_weakref_register(obj_key, ZEND_WEAKREF_ENCODE(wm, ZEND_WEAKREF_TAG_MAP));
|
||||
zend_weakref_register(obj_key, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP));
|
||||
zend_hash_index_add_new(&wm->ht, (zend_ulong) obj_key, value);
|
||||
}
|
||||
|
||||
|
@ -378,7 +394,7 @@ static void zend_weakmap_unset_dimension(zend_object *object, zval *offset)
|
|||
return;
|
||||
}
|
||||
|
||||
zend_weakref_unregister(obj_key, ZEND_WEAKREF_ENCODE(wm, ZEND_WEAKREF_TAG_MAP));
|
||||
zend_weakref_unregister(obj_key, ZEND_WEAKREF_ENCODE(&wm->ht, ZEND_WEAKREF_TAG_MAP));
|
||||
}
|
||||
|
||||
static int zend_weakmap_count_elements(zend_object *object, zend_long *count)
|
||||
|
|
|
@ -28,6 +28,18 @@ void zend_weakrefs_shutdown(void);
|
|||
|
||||
ZEND_API void zend_weakrefs_notify(zend_object *object);
|
||||
|
||||
ZEND_API zval *zend_weakrefs_hash_add(HashTable *ht, zend_object *key, zval *pData);
|
||||
ZEND_API zend_result zend_weakrefs_hash_del(HashTable *ht, zend_object *key);
|
||||
static zend_always_inline void *zend_weakrefs_hash_add_ptr(HashTable *ht, zend_object *key, void *ptr) {
|
||||
zval tmp, *zv;
|
||||
ZVAL_PTR(&tmp, ptr);
|
||||
if ((zv = zend_weakrefs_hash_add(ht, key, &tmp))) {
|
||||
return Z_PTR_P(zv);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "zend_attributes.h"
|
||||
#include "zend_observer.h"
|
||||
#include "zend_smart_str.h"
|
||||
#include "zend_weakrefs.h"
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(zend_test)
|
||||
int observer_enabled;
|
||||
|
@ -41,6 +42,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
|
|||
int observer_show_opcode;
|
||||
int observer_nesting_depth;
|
||||
int replace_zend_execute_ex;
|
||||
HashTable global_weakmap;
|
||||
ZEND_END_MODULE_GLOBALS(zend_test)
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
|
||||
|
@ -225,6 +227,40 @@ static ZEND_FUNCTION(zend_string_or_stdclass_or_null)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static ZEND_FUNCTION(zend_weakmap_attach)
|
||||
{
|
||||
zval *value;
|
||||
zend_object *obj;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 2)
|
||||
Z_PARAM_OBJ(obj)
|
||||
Z_PARAM_ZVAL(value)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (zend_weakrefs_hash_add(&ZT_G(global_weakmap), obj, value)) {
|
||||
Z_TRY_ADDREF_P(value);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
static ZEND_FUNCTION(zend_weakmap_remove)
|
||||
{
|
||||
zend_object *obj;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||
Z_PARAM_OBJ(obj)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
RETURN_BOOL(zend_weakrefs_hash_del(&ZT_G(global_weakmap), obj) == SUCCESS);
|
||||
}
|
||||
|
||||
static ZEND_FUNCTION(zend_weakmap_dump)
|
||||
{
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
RETURN_ARR(zend_array_dup(&ZT_G(global_weakmap)));
|
||||
}
|
||||
|
||||
/* TESTS Z_PARAM_ITERABLE and Z_PARAM_ITERABLE_OR_NULL */
|
||||
static ZEND_FUNCTION(zend_iterable)
|
||||
{
|
||||
|
@ -622,11 +658,17 @@ static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execu
|
|||
|
||||
PHP_RINIT_FUNCTION(zend_test)
|
||||
{
|
||||
zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(zend_test)
|
||||
{
|
||||
zend_ulong objptr;
|
||||
ZEND_HASH_FOREACH_NUM_KEY(&ZT_G(global_weakmap), objptr) {
|
||||
zend_weakrefs_hash_del(&ZT_G(global_weakmap), (zend_object *)(uintptr_t)objptr);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
zend_hash_destroy(&ZT_G(global_weakmap));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,10 @@ function zend_string_or_stdclass_or_null($param): stdClass|string|null {}
|
|||
|
||||
function zend_iterable(iterable $arg1, ?iterable $arg2 = null): void {}
|
||||
|
||||
function zend_weakmap_attach(object $object, mixed $value): bool {}
|
||||
function zend_weakmap_remove(object $object): bool {}
|
||||
function zend_weakmap_dump(): array {}
|
||||
|
||||
}
|
||||
|
||||
namespace ZendTestNS {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 3240b7fa3461b40a211371250c4975802f44185b */
|
||||
* Stub hash: 49b9abbc5ce826e749861fd511e98f1add001368 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -51,6 +51,17 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_iterable, 0, 1, IS_VOID, 0)
|
|||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, arg2, IS_ITERABLE, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_weakmap_attach, 0, 2, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_weakmap_remove, 0, 1, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_zend_weakmap_dump arginfo_zend_test_array_return
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_ZendSubNS_namespaced_func, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
@ -83,6 +94,9 @@ static ZEND_FUNCTION(zend_string_or_object_or_null);
|
|||
static ZEND_FUNCTION(zend_string_or_stdclass);
|
||||
static ZEND_FUNCTION(zend_string_or_stdclass_or_null);
|
||||
static ZEND_FUNCTION(zend_iterable);
|
||||
static ZEND_FUNCTION(zend_weakmap_attach);
|
||||
static ZEND_FUNCTION(zend_weakmap_remove);
|
||||
static ZEND_FUNCTION(zend_weakmap_dump);
|
||||
static ZEND_FUNCTION(namespaced_func);
|
||||
static ZEND_METHOD(_ZendTestClass, is_object);
|
||||
static ZEND_METHOD(_ZendTestClass, __toString);
|
||||
|
@ -106,6 +120,9 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(zend_string_or_stdclass, arginfo_zend_string_or_stdclass)
|
||||
ZEND_FE(zend_string_or_stdclass_or_null, arginfo_zend_string_or_stdclass_or_null)
|
||||
ZEND_FE(zend_iterable, arginfo_zend_iterable)
|
||||
ZEND_FE(zend_weakmap_attach, arginfo_zend_weakmap_attach)
|
||||
ZEND_FE(zend_weakmap_remove, arginfo_zend_weakmap_remove)
|
||||
ZEND_FE(zend_weakmap_dump, arginfo_zend_weakmap_dump)
|
||||
ZEND_NS_FE("ZendTestNS2\\ZendSubNS", namespaced_func, arginfo_ZendTestNS2_ZendSubNS_namespaced_func)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
|
54
ext/zend_test/tests/zend_weakmap.phpt
Normal file
54
ext/zend_test/tests/zend_weakmap.phpt
Normal file
|
@ -0,0 +1,54 @@
|
|||
--TEST--
|
||||
Test internal weakmap API
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$id1 = new \stdClass;
|
||||
$id2 = new \stdClass;
|
||||
|
||||
var_dump(zend_weakmap_attach($id1, 1));
|
||||
var_dump(zend_weakmap_attach($id1, 3));
|
||||
var_dump(zend_weakmap_attach($id2, 2));
|
||||
|
||||
var_dump(zend_weakmap_dump());
|
||||
|
||||
unset($id1);
|
||||
|
||||
var_dump(zend_weakmap_dump());
|
||||
|
||||
var_dump(zend_weakmap_remove($id2));
|
||||
var_dump(zend_weakmap_remove($id2));
|
||||
|
||||
var_dump(zend_weakmap_dump());
|
||||
|
||||
var_dump(zend_weakmap_attach($id2, $id2));
|
||||
|
||||
var_dump(zend_weakmap_dump());
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
bool(false)
|
||||
bool(true)
|
||||
array(2) {
|
||||
[%d]=>
|
||||
int(1)
|
||||
[%d]=>
|
||||
int(2)
|
||||
}
|
||||
array(1) {
|
||||
[%d]=>
|
||||
int(2)
|
||||
}
|
||||
bool(true)
|
||||
bool(false)
|
||||
array(0) {
|
||||
}
|
||||
bool(true)
|
||||
array(1) {
|
||||
[%d]=>
|
||||
object(stdClass)#2 (0) {
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue