diff options
author | Andi Gutmans <andi@php.net> | 2001-12-27 14:35:09 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2001-12-27 14:35:09 +0000 |
commit | 73b159e0567683f96a2da78d7a2e60cf0f6f0bbc (patch) | |
tree | 5d077c4f72a7868f75649cf12a2f2b23e684ed6c /Zend/zend_objects.c | |
parent | b3fd2faac06a6f9f216070b00ad46c13309fa6b3 (diff) | |
download | php-git-73b159e0567683f96a2da78d7a2e60cf0f6f0bbc.tar.gz |
- Experimental support for destructors. We need to see if destructors
- will actually work well in the context of PHP so we should consider this
- as experimental. Possible problems might be that when the constructor is
- run PHP might not be in a stable state.
Diffstat (limited to 'Zend/zend_objects.c')
-rw-r--r-- | Zend/zend_objects.c | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index f86148158d..776f7d9076 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -27,6 +27,43 @@ void zend_objects_destroy(zend_objects *objects) efree(objects->object_buckets); } +static inline void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC) +{ + if (object->ce->destructor) { + zval *obj; + zval *destructor_func_name; + zval *retval_ptr; + HashTable symbol_table; + + MAKE_STD_ZVAL(obj); + obj->type = IS_OBJECT; + obj->value.obj.handle = handle; + obj->value.obj.handlers = &zoh; + zval_copy_ctor(obj); + + + /* FIXME: Optimize this so that we use the old_object->ce->destructor function pointer instead of the name */ + MAKE_STD_ZVAL(destructor_func_name); + destructor_func_name->type = IS_STRING; + destructor_func_name->value.str.val = estrndup("_destruct", sizeof("_destruct")-1); + destructor_func_name->value.str.len = sizeof("_destruct")-1; + + ZEND_INIT_SYMTABLE(&symbol_table); + + call_user_function_ex(NULL, &obj, destructor_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC); + + zend_hash_destroy(&symbol_table); + zval_ptr_dtor(&obj); + zval_ptr_dtor(&destructor_func_name); + zval_ptr_dtor(&retval_ptr); + } + + /* Nuke the object */ + zend_hash_destroy(object->properties); + efree(object->properties); + +} + zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type) { zend_object_handle handle; @@ -45,6 +82,7 @@ zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class handle = EG(objects).top++; } EG(objects).object_buckets[handle].valid = 1; + EG(objects).object_buckets[handle].constructor_called = 0; EG(objects).object_buckets[handle].bucket.obj.refcount = 1; *object = &EG(objects).object_buckets[handle].bucket.obj.object; @@ -93,9 +131,14 @@ void zend_objects_delete_obj(zend_object_handle handle) } object = &EG(objects).object_buckets[handle].bucket.obj.object; - zend_hash_destroy(object->properties); - efree(object->properties); + + if (!EG(objects).object_buckets[handle].constructor_called) { + EG(objects).object_buckets[handle].constructor_called = 1; + zend_objects_destroy_object(object, handle TSRMLS_CC); + } + EG(objects).object_buckets[handle].valid = 0; + #if ZEND_DEBUG_OBJECTS fprintf(stderr, "Deleted object id #%d\n", handle); #endif @@ -110,13 +153,18 @@ void zend_objects_del_ref(zend_object_handle handle) zend_object *object; if (EG(objects).object_buckets[handle].valid) { - object = &EG(objects).object_buckets[handle].bucket.obj.object; - zend_hash_destroy(object->properties); - efree(object->properties); + if (!EG(objects).object_buckets[handle].constructor_called) { + object = &EG(objects).object_buckets[handle].bucket.obj.object; + EG(objects).object_buckets[handle].constructor_called = 1; + zend_objects_destroy_object(object, handle TSRMLS_CC); + } + } + /* FIXME: Optimizer this so that only if the constructor was called we recheck the refcount */ + if (EG(objects).object_buckets[handle].bucket.obj.refcount == 0) { + EG(objects).object_buckets[handle].bucket.free_list.next = EG(objects).free_list_head; + EG(objects).free_list_head = handle; + EG(objects).object_buckets[handle].valid = 0; } - EG(objects).object_buckets[handle].bucket.free_list.next = EG(objects).free_list_head; - EG(objects).free_list_head = handle; - EG(objects).object_buckets[handle].valid = 0; #if ZEND_DEBUG_OBJECTS fprintf(stderr, "Deallocated object id #%d\n", handle); #endif |