X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pq_callback.c;h=2b58b40034494857ddac31e75d6e11693b15992c;hp=6b0213f8ac5ed744ce58c4a685d419bcb5fd5149;hb=HEAD;hpb=6e28a8741be3fccdaca960e492c31bc26837a4ed diff --git a/src/php_pq_callback.c b/src/php_pq_callback.c index 6b0213f..2b58b40 100644 --- a/src/php_pq_callback.c +++ b/src/php_pq_callback.c @@ -30,7 +30,10 @@ void php_pq_callback_dtor(php_pq_callback_t *cb) zend_fcall_info_args_clear(&cb->fci, 1); zval_ptr_dtor(&cb->fci.function_name); if (cb->fci.object) { - zend_objects_store_del(cb->fci.object); + zval tmp; + + ZVAL_OBJ(&tmp, cb->fci.object); + zval_ptr_dtor(&tmp); } cb->fci.size = 0; } @@ -40,7 +43,11 @@ void php_pq_callback_addref(php_pq_callback_t *cb) { Z_TRY_ADDREF(cb->fci.function_name); if (cb->fci.object) { +#ifdef GC_ADDREF + GC_ADDREF(cb->fci.object); +#else ++GC_REFCOUNT(cb->fci.object); +#endif } } @@ -62,39 +69,98 @@ zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *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 (php_pq_callback_is_enabled(cb)) { + const zend_function *closure; + const zend_execute_data *ex; - if (closure->type == ZEND_USER_FUNCTION) { - zend_execute_data *ex = EG(current_execute_data); + if (Z_TYPE_P(cb->fci.function_name) != IS_OBJECT) { + return 0; + } + + closure = zend_get_closure_method_def(cb->fci.function_name); + if (closure->type != ZEND_USER_FUNCTION) { + return 0; + } - while (ex) { - if (ex->op_array == &closure->op_array) { - return 1; - } - ex = ex->prev_execute_data; + for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { + if (ex->op_array == &closure->op_array) { + return 1; } } } + if (!php_pq_callback_is_recurrent(cb)) { + return 0; + } + return php_pq_callback_is_locked(cb->recursion); */ return 0; } -void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC) +void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new) { - 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) { + if (php_pq_callback_is_locked(old)) { + php_pq_callback_recurse_ex(old, new); + } else { php_pq_callback_dtor(old); - php_pq_callback_addref(new); + if (php_pq_callback_is_enabled(new)) { + php_pq_callback_addref(new); + memcpy(old, new, sizeof(*old)); + new->fci.size = 0; + } + } +} + +extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb) +{ + return cb && cb->fci.size > 0; +} + +extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb) +{ + return cb && cb->recursion != NULL; +} + +extern void php_pq_callback_disable(php_pq_callback_t *cb) +{ + if (php_pq_callback_is_enabled(cb)) { + php_pq_callback_recurse_ex(cb, NULL); + } +} + +extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new) +{ + php_pq_callback_t *tmp = emalloc(sizeof(*tmp)); + + if (new) { + memcpy(tmp, old, sizeof(*tmp)); memcpy(old, new, sizeof(*old)); - new->fci.size = 0; + old->recursion = tmp; + + php_pq_callback_addref(old); + php_pq_callback_disable(tmp); } else { - php_pq_callback_dtor(old); + memcpy(tmp, old, sizeof(*tmp)); + memset(old, 0, sizeof(*old)); + old->recursion = tmp; } }