fix issue #9 @github: execAsync - gets another result
[m6w6/ext-pq] / src / php_pq_callback.c
index 63f2edc4bab570523b133bcf027c1a4bb94e9b95..de01c37ac13b48c5481e77b7e97c152f175c0d39 100644 (file)
@@ -64,35 +64,78 @@ zval *php_pq_callback_to_zval(php_pq_callback_t *cb)
 
 zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb TSRMLS_DC)
 {
-       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 TSRMLS_CC);
+       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 TSRMLS_CC);
+               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;
                        }
                }
        }
-       return 0;
+
+       if (!php_pq_callback_is_recurrent(cb)) {
+               return 0;
+       }
+       return php_pq_callback_is_locked(cb->recursion TSRMLS_CC);
 }
 
 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) {
+       if (php_pq_callback_is_locked(old TSRMLS_CC)) {
+               php_pq_callback_recurse_ex(old, new TSRMLS_CC);
+       } 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 TSRMLS_DC)
+{
+       if (php_pq_callback_is_enabled(cb)) {
+               php_pq_callback_recurse_ex(cb, NULL TSRMLS_CC);
+       }
+}
+
+extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
+{
+       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 TSRMLS_CC);
        } else {
-               php_pq_callback_dtor(old);
+               memcpy(tmp, old, sizeof(*tmp));
+               memset(old, 0, sizeof(*old));
+               old->recursion = tmp;
        }
 }