From e1866703d7f0f323f191cde1df926f16d7cfe1bc Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Fri, 3 Jul 2009 12:04:02 +0900 Subject: [PATCH] * Always return the same wrapper object for the same C++ object. --- boost/php/klass.hpp | 81 ++++++++++++++++++++++++++++----------------- tests/m008.phpt | 11 ++++++ 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/boost/php/klass.hpp b/boost/php/klass.hpp index 096e4f0..c134970 100644 --- a/boost/php/klass.hpp +++ b/boost/php/klass.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,9 @@ class klass: public ::zend_class_entry, public function_container >, p typedef zo_wrapper_tpl zo_wrapper; friend struct to_value_ptr_converter; +private: + typedef boost::unordered_map instance_handle_map; + public: klass(char const* _name) { TSRMLS_FETCH(); @@ -262,21 +266,6 @@ class klass: public ::zend_class_entry, public function_container >, p return retval; } - static ::zend_object_value __ptr_factory(klass* self, object_type *ptr, void(*destroy_handler)(object_type* TSRMLS_DC) TSRMLS_DC) { - zend_object_value retval; - - zo_wrapper* obj = new zo_wrapper(*self, ptr, destroy_handler TSRMLS_CC); - obj->handle = retval.handle = ::zend_objects_store_put(obj, - reinterpret_cast< ::zend_objects_store_dtor_t>(&__dtor_wrapper), - reinterpret_cast< ::zend_objects_free_object_storage_t>( - &__delete_wrapper), - reinterpret_cast< ::zend_objects_store_clone_t>( - &__cctor_wrapper) - TSRMLS_CC); - retval.handlers = ::zend_get_std_object_handlers(); - return retval; - } - static void __deleter(object_type* ptr TSRMLS_DC) { delete ptr; @@ -285,14 +274,22 @@ class klass: public ::zend_class_entry, public function_container >, p static ::zend_object_value __weakref_factory(klass* self, object_type* ptr, void(*destroy_handler)(object_type* TSRMLS_DC) = 0 TSRMLS_DC) { zend_object_value retval; - zo_wrapper* obj = new zo_wrapper(*self, ptr, destroy_handler TSRMLS_CC); - obj->handle = retval.handle = ::zend_objects_store_put(obj, - reinterpret_cast< ::zend_objects_store_dtor_t>(&__dtor_wrapper), - reinterpret_cast< ::zend_objects_free_object_storage_t>( - &__delete_wrapper), - reinterpret_cast< ::zend_objects_store_clone_t>( - &__cctor_wrapper) - TSRMLS_CC); + typename instance_handle_map::const_iterator i(weakref_handle_map_.find(ptr)); + if (weakref_handle_map_.end() != i) { + retval.handle = (*i).second; + zend_objects_store_add_ref_by_handle(retval.handle TSRMLS_CC); + } else { + zo_wrapper* obj = new zo_wrapper(*self, ptr, destroy_handler TSRMLS_CC); + retval.handle = obj->handle = ::zend_objects_store_put(obj, + reinterpret_cast< ::zend_objects_store_dtor_t>( + &__dtor_wrapper), + reinterpret_cast< ::zend_objects_free_object_storage_t>( + &__delete_wrapper), + reinterpret_cast< ::zend_objects_store_clone_t>( + &__cctor_wrapper) + TSRMLS_CC); + weakref_handle_map_.insert(std::make_pair(ptr, retval.handle)); + } retval.handlers = ::zend_get_std_object_handlers(); return retval; } @@ -300,14 +297,22 @@ class klass: public ::zend_class_entry, public function_container >, p static ::zend_object_value __ref_factory(klass* self, typename zo_wrapper::shared_pointer ptr TSRMLS_DC) { zend_object_value retval; - zo_wrapper* obj = new zo_wrapper(*self, ptr TSRMLS_CC); - obj->handle = retval.handle = ::zend_objects_store_put(obj, - reinterpret_cast< ::zend_objects_store_dtor_t>(&__dtor_wrapper), - reinterpret_cast< ::zend_objects_free_object_storage_t>( - &__delete_wrapper), - reinterpret_cast< ::zend_objects_store_clone_t>( - &__cctor_wrapper) - TSRMLS_CC); + typename instance_handle_map::const_iterator i(ref_handle_map_.find(ptr.get())); + if (ref_handle_map_.end() != i) { + retval.handle = (*i).second; + zend_objects_store_add_ref_by_handle(retval.handle TSRMLS_CC); + } else { + zo_wrapper* obj = new zo_wrapper(*self, ptr TSRMLS_CC); + retval.handle = obj->handle = ::zend_objects_store_put(obj, + reinterpret_cast< ::zend_objects_store_dtor_t>( + &__dtor_wrapper), + reinterpret_cast< ::zend_objects_free_object_storage_t>( + &__delete_wrapper), + reinterpret_cast< ::zend_objects_store_clone_t>( + &__cctor_wrapper) + TSRMLS_CC); + ref_handle_map_.insert(std::make_pair(ptr.get(), retval.handle)); + } retval.handlers = ::zend_get_std_object_handlers(); return retval; } @@ -315,9 +320,12 @@ class klass: public ::zend_class_entry, public function_container >, p static void __dtor_wrapper(zo_wrapper* obj TSRMLS_DC) { if (obj->type == zo_wrapper::REF) { + ref_handle_map_.erase(obj->ptr); typedef typename zo_wrapper::shared_pointer shared_pointer; reinterpret_cast(obj->ref)->~shared_pointer(); } else { + if (obj->type == zo_wrapper::WEAKREF) + weakref_handle_map_.erase(obj->ptr); if (obj->destroy_handler) obj->destroy_handler(obj->ptr TSRMLS_CC); } @@ -330,8 +338,19 @@ class klass: public ::zend_class_entry, public function_container >, p static void __cctor_wrapper(zo_wrapper* obj, zo_wrapper** cloned_obj TSRMLS_DC) { *cloned_obj = new zo_wrapper(*obj TSRMLS_CC); } + + static instance_handle_map weakref_handle_map_; + static instance_handle_map ref_handle_map_; }; +template +typename klass::instance_handle_map +klass::weakref_handle_map_; + +template +typename klass::instance_handle_map +klass::ref_handle_map_; + template T_* object_retriever::operator()(INTERNAL_FUNCTION_PARAMETERS) const { diff --git a/tests/m008.phpt b/tests/m008.phpt index 108cd19..9945e33 100644 --- a/tests/m008.phpt +++ b/tests/m008.phpt @@ -10,38 +10,49 @@ $test2 = new test(2); for ($i = 0; $i < 10; ++$i) { $test1->accumulate($i); test::foo($test1); + var_dump($test2 == $test2->self()); var_dump($test2->self()->self()->accumulate(10-$i)); echo "--\n"; } ?> --EXPECT-- 1 +bool(true) int(12) -- 2 +bool(true) int(21) -- 4 +bool(true) int(29) -- 7 +bool(true) int(36) -- 11 +bool(true) int(42) -- 16 +bool(true) int(47) -- 22 +bool(true) int(51) -- 29 +bool(true) int(54) -- 37 +bool(true) int(56) -- 46 +bool(true) int(57) --