Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Some weakmap magic

  • Loading branch information...
commit 92c5417d3ef156bd5bde3fe3d67d706b42aba2f3 1 parent c1bccc3
@colder authored
View
6 php_weakref.c
@@ -51,7 +51,7 @@ void wr_store_destroy(TSRMLS_D) /* {{{ */
WR_G(store) = NULL;
} /* }}} */
-void wr_store_dtor(void *object, zend_object_handle ref_handle TSRMLS_DC) /* {{{ */
+void wr_store_dtor(void *ref_object, zend_object_handle ref_handle TSRMLS_DC) /* {{{ */
{
wr_store *store = WR_G(store);
zend_objects_store_dtor_t orig_dtor = store->objs[ref_handle].orig_dtor;
@@ -60,11 +60,11 @@ void wr_store_dtor(void *object, zend_object_handle ref_handle TSRMLS_DC) /* {{{
EG(objects_store).object_buckets[ref_handle].bucket.obj.dtor = data.orig_dtor;
- orig_dtor(object, ref_handle TSRMLS_CC);
+ orig_dtor(ref_object, ref_handle TSRMLS_CC);
while (list_entry != NULL) {
wr_ref_list *next = list_entry->next;
- list_entry->dtor(object, list_entry->obj TSRMLS_CC);
+ list_entry->dtor(ref_object, ref_handle, list_entry->obj TSRMLS_CC);
efree(list_entry);
list_entry = next;
}
View
18 php_weakref.h
@@ -43,23 +43,7 @@ PHP_MINIT_FUNCTION(weakref);
PHP_RINIT_FUNCTION(weakref);
PHP_RSHUTDOWN_FUNCTION(weakref);
-typedef struct _wr_weakref_object {
- zend_object std;
- zval *ref;
- zend_bool valid;
- unsigned int acquired;
-} wr_weakref_object;
-
-typedef struct _wr_weakmap_object {
- zend_object std;
- zend_function *fptr_offset_get;
- zend_function *fptr_offset_set;
- zend_function *fptr_offset_has;
- zend_function *fptr_offset_del;
- zend_function *fptr_count;
-} wr_weakmap_object;
-
-typedef void (*wr_ref_dtor)(void *object, zend_object *wref_obj TSRMLS_DC);
+typedef void (*wr_ref_dtor)(void *ref_object, zend_object_handle ref_handle, zend_object *wref_obj TSRMLS_DC);
typedef struct _wr_ref_list {
zend_object *obj;
View
108 wr_weakmap.c
@@ -30,48 +30,23 @@
#include "php_weakref.h"
-static void wr_weakmap_ref_dtor(void *object, zend_object *wref_obj TSRMLS_DC) { /* {{{ */
- /*
- wr_weakref_object *wref = (wr_weakref_object *)wref_obj;
- wref->valid = 0;
- wref->ref = NULL;
- */
+static void wr_weakmap_ref_dtor(void *ref_object, zend_object_handle ref_handle, zend_object *wref_obj TSRMLS_DC) { /* {{{ */
+ wr_weakmap_object *intern = (wr_weakmap_object *)wref_obj;
+
+ zend_hash_index_del(&intern->map, ref_handle);
}
/* }}} */
static void wr_weakmap_object_free_storage(void *object TSRMLS_DC) /* {{{ */
{
- /*
- wr_weakref_object *intern = (wr_weakref_object *)object;
-
- if (intern->valid) {
- zend_object_handle ref_handle = Z_OBJ_HANDLE_P(intern->ref);
- wr_store *store = WR_G(store);
-
- wr_store_data *data = &store->objs[ref_handle];
- wr_ref_list *prev = NULL;
- wr_ref_list *cur = data->wrefs_head;
-
- while (cur && cur->obj != (zend_object *)intern) {
- prev = cur;
- cur = cur->next;
- }
-
- assert(cur != NULL);
-
- if (prev) {
- prev->next = cur->next;
- } else {
- data->wrefs_head = cur->next;
- }
- efree(cur);
- }
+ wr_weakmap_object *intern = (wr_weakmap_object *)object;
zend_object_std_dtor(&intern->std TSRMLS_CC);
- efree(object);
- */
+ zend_hash_destroy(&intern->map);
+
+ efree(intern);
}
/* }}} */
@@ -97,6 +72,8 @@ static zend_object_value wr_weakmap_object_new_ex(zend_class_entry *class_type,
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
#endif
+ zend_hash_init(&intern->map, 0, NULL, ZVAL_PTR_DTOR, 0);
+
if (clone_orig && orig) {
wr_weakmap_object *other = (wr_weakmap_object *)zend_object_store_get_object(orig TSRMLS_CC);
//TODO
@@ -159,31 +136,27 @@ static zend_object_value wr_weakmap_object_new(zend_class_entry *class_type TSRM
}
/* }}} */
-static inline zval **wr_weakmap_object_read_dimension_helper(wr_weakmap_object *intern, zval *offset TSRMLS_DC) /* {{{ */
+static inline zval *wr_weakmap_object_read_dimension_helper(wr_weakmap_object *intern, zval *offset TSRMLS_DC) /* {{{ */
{
- long index;
+ zval *retval;
- /* we have to return NULL on error here to avoid memleak because of
- * ZE duplicating uninitialized_zval_ptr */
- if (!offset) {
+ if (!offset || Z_TYPE_P(offset) != IS_OBJECT) {
zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
return NULL;
}
- if (Z_TYPE_P(offset) != IS_OBJECT) {
- zend_throw_exception(spl_ce_RuntimeException, "Index is not an object", 0 TSRMLS_CC);
- return NULL;
+ if (zend_hash_index_find(&intern->map, Z_OBJ_HANDLE_P(offset), (void**)&retval) == FAILURE) {
+ retval = NULL;
}
-
- //TODO
- return NULL;
+
+ return retval;
}
/* }}} */
static zval *wr_weakmap_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
{
wr_weakmap_object *intern;
- zval **retval;
+ zval *retval;
intern = (wr_weakmap_object *)zend_object_store_get_object(object TSRMLS_CC);
@@ -201,7 +174,7 @@ static zval *wr_weakmap_object_read_dimension(zval *object, zval *offset, int ty
retval = wr_weakmap_object_read_dimension_helper(intern, offset TSRMLS_CC);
if (retval) {
- return *retval;
+ return retval;
}
return NULL;
}
@@ -209,11 +182,8 @@ static zval *wr_weakmap_object_read_dimension(zval *object, zval *offset, int ty
static inline void wr_weakmap_object_write_dimension_helper(wr_weakmap_object *intern, zval *offset, zval *value TSRMLS_DC) /* {{{ */
{
- long index;
-
if (!offset) {
- /* '$array[] = value' syntax is not supported */
- zend_throw_exception(spl_ce_RuntimeException, "Index invalid or out of range", 0 TSRMLS_CC);
+ zend_throw_exception(spl_ce_RuntimeException, "WeakMap does not support [] (append)", 0 TSRMLS_CC);
return;
}
@@ -222,7 +192,17 @@ static inline void wr_weakmap_object_write_dimension_helper(wr_weakmap_object *i
return;
}
- //TODO
+ if (!zend_hash_index_exists(&intern->map, Z_OBJ_HANDLE_P(offset))) {
+ // Object not already in the weakmap, we attach it
+ wr_store_attach((zend_object *)intern, wr_weakmap_ref_dtor, offset TSRMLS_CC);
+ }
+
+ Z_ADDREF_P(value);
+ if (zend_hash_index_update(&intern->map, Z_OBJ_HANDLE_P(offset), &value, sizeof(zval *), NULL) == FAILURE) {
+ zend_throw_exception(spl_ce_RuntimeException, "Failed to update the map", 0 TSRMLS_CC);
+ zval_ptr_dtor(&value);
+ return;
+ }
}
/* }}} */
@@ -256,7 +236,7 @@ static inline void wr_weakmap_object_unset_dimension_helper(wr_weakmap_object *i
return;
}
- // TODO
+ zend_hash_index_del(&intern->map, Z_OBJ_HANDLE_P(offset));
}
/* }}} */
@@ -280,16 +260,12 @@ static void wr_weakmap_object_unset_dimension(zval *object, zval *offset TSRMLS_
static inline int wr_weakmap_object_has_dimension_helper(wr_weakmap_object *intern, zval *offset, int check_empty TSRMLS_DC) /* {{{ */
{
- int retval = 0;
-
if (Z_TYPE_P(offset) != IS_OBJECT) {
zend_throw_exception(spl_ce_RuntimeException, "Index is not an object", 0 TSRMLS_CC);
- return;
+ return 0;
}
- // TODO
-
- return retval;
+ return zend_hash_index_exists(&intern->map, Z_OBJ_HANDLE_P(offset));
}
/* }}} */
@@ -319,8 +295,9 @@ static int wr_weakmap_object_has_dimension(zval *object, zval *offset, int check
static int wr_weakmap_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
{
wr_weakmap_object *intern;
-
+
intern = (wr_weakmap_object *)zend_object_store_get_object(object TSRMLS_CC);
+
if (intern->fptr_count) {
zval *rv;
zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
@@ -335,8 +312,7 @@ static int wr_weakmap_object_count_elements(zval *object, long *count TSRMLS_DC)
}
}
- // TODO
- *count = 0;
+ *count = zend_hash_num_elements(&intern->map);
return SUCCESS;
}
/* }}} */
@@ -388,18 +364,18 @@ PHP_METHOD(WeakMap, offsetExists)
Returns the value at the specified $index. */
PHP_METHOD(WeakMap, offsetGet)
{
- zval *zindex, **value_pp;
+ zval *zindex, *value_p;
wr_weakmap_object *intern;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
return;
}
- intern = (wr_weakmap_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
- value_pp = wr_weakmap_object_read_dimension_helper(intern, zindex TSRMLS_CC);
+ intern = (wr_weakmap_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
+ value_p = wr_weakmap_object_read_dimension_helper(intern, zindex TSRMLS_CC);
- if (value_pp) {
- RETURN_ZVAL(*value_pp, 1, 0);
+ if (value_p) {
+ RETURN_ZVAL(value_p, 1, 0);
}
RETURN_NULL();
} /* }}} */
View
10 wr_weakmap.h
@@ -23,6 +23,16 @@
#include "php_weakref.h"
+typedef struct _wr_weakmap_object {
+ zend_object std;
+ HashTable map;
+ zend_function *fptr_offset_get;
+ zend_function *fptr_offset_set;
+ zend_function *fptr_offset_has;
+ zend_function *fptr_offset_del;
+ zend_function *fptr_count;
+} wr_weakmap_object;
+
extern WEAKREF_API zend_class_entry *wr_ce_WeakMap;
zend_object_handlers wr_handler_WeakMap;
View
2  wr_weakref.c
@@ -30,7 +30,7 @@
#include "php_weakref.h"
-static void wr_weakref_ref_dtor(void *object, zend_object *wref_obj TSRMLS_DC) { /* {{{ */
+static void wr_weakref_ref_dtor(void *ref_object, zend_object_handle ref_handle, zend_object *wref_obj TSRMLS_DC) { /* {{{ */
wr_weakref_object *wref = (wr_weakref_object *)wref_obj;
wref->valid = 0;
wref->ref = NULL;
View
7 wr_weakref.h
@@ -23,6 +23,13 @@
#include "php_weakref.h"
+typedef struct _wr_weakref_object {
+ zend_object std;
+ zval *ref;
+ zend_bool valid;
+ unsigned int acquired;
+} wr_weakref_object;
+
extern WEAKREF_API zend_class_entry *wr_ce_WeakRef;
zend_object_handlers wr_handler_WeakRef;
Please sign in to comment.
Something went wrong with that request. Please try again.