X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Fphp_pq_callback.c;h=695d5920dddddb8d5251703da10a3fb889009c3a;hb=baafbf6c24c8f272b714d3829857eca3833bca3e;hp=1f02a450f2eeaf3a7277a726b0e94d0435ce97d0;hpb=9f5cecf26bd70a92ed013f31afec59e272623ac1;p=m6w6%2Fext-pq diff --git a/src/php_pq_callback.c b/src/php_pq_callback.c index 1f02a45..695d592 100644 --- a/src/php_pq_callback.c +++ b/src/php_pq_callback.c @@ -15,26 +15,105 @@ #endif #include +#include #include "php_pq_callback.h" void php_pq_callback_dtor(php_pq_callback_t *cb) { + if (cb->recursion) { + php_pq_callback_dtor(cb->recursion); + efree(cb->recursion); + cb->recursion = NULL; + } if (cb->fci.size > 0) { zend_fcall_info_args_clear(&cb->fci, 1); zval_ptr_dtor(&cb->fci.function_name); - if (cb->fci.object_ptr) { - zval_ptr_dtor(&cb->fci.object_ptr); + if (cb->fci.object) { + zval tmp; + + ZVAL_OBJ(&tmp, cb->fci.object); + zval_ptr_dtor(&tmp); } + cb->fci.size = 0; } - cb->fci.size = 0; } void php_pq_callback_addref(php_pq_callback_t *cb) { - Z_ADDREF_P(cb->fci.function_name); - if (cb->fci.object_ptr) { - Z_ADDREF_P(cb->fci.object_ptr); + Z_TRY_ADDREF(cb->fci.function_name); + if (cb->fci.object) { + ++GC_REFCOUNT(cb->fci.object); + } +} + +zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp) +{ + php_pq_callback_addref(cb); + + if (cb->fci.object) { + zval zo; + + array_init_size(tmp, 2); + ZVAL_OBJ(&zo, cb->fci.object); + add_next_index_zval(tmp, &zo); + add_next_index_zval(tmp, &cb->fci.function_name); + + return tmp; + } + + return &cb->fci.function_name; +} + +zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp) +{ + if (cb->fci.object) { + zval zo; + + array_init_size(tmp, 2); + ZVAL_OBJ(&zo, cb->fci.object); + add_next_index_zval(tmp, &zo); + add_next_index_zval(tmp, &cb->fci.function_name); + + return tmp; + } + + return &cb->fci.function_name; +} + +zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb) +{ + /* TODO: fixed in php7? + if (cb->fci.size > 0 && Z_TYPE_P(cb->fci.function_name) == IS_OBJECT) { + const zend_function *closure = zend_get_closure_method_def(cb->fci.function_name); + + if (closure->type == ZEND_USER_FUNCTION) { + zend_execute_data *ex = EG(current_execute_data); + + while (ex) { + if (ex->op_array == &closure->op_array) { + return 1; + } + ex = ex->prev_execute_data; + } + } + } + */ + return 0; +} + +void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC) +{ + if (new && new->fci.size > 0 && php_pq_callback_is_locked(old TSRMLS_CC)) { + new->recursion = emalloc(sizeof(*old)); + memcpy(new->recursion, old, sizeof(*old)); + } else if (new && new->fci.size > 0) { + php_pq_callback_dtor(old); + php_pq_callback_addref(new); + memcpy(old, new, sizeof(*old)); + new->fci.size = 0; + } else { + php_pq_callback_dtor(old); } }