@@ -624,7 +624,6 @@ struct _zend_async_task_s {
624624
625625typedef void (* zend_async_before_coroutine_enqueue_t )(zend_coroutine_t * coroutine , zend_async_scope_t * scope , zval * result );
626626typedef void (* zend_async_after_coroutine_enqueue_t )(zend_coroutine_t * coroutine , zend_async_scope_t * scope );
627- typedef void (* zend_async_scope_dispose_t )(zend_async_scope_t * scope );
628627
629628/* Dynamic array of async event callbacks */
630629typedef struct _zend_async_scopes_vector_s {
@@ -641,13 +640,12 @@ typedef struct _zend_async_scopes_vector_s {
641640 * it initiates the disposal process of the Scope.
642641 *
643642 * However, the internal Scope structure remains in memory until the last coroutine has completed.
644- *
645643 */
646644struct _zend_async_scope_s {
647- /* The scope ZEND_ASYNC_SCOPE_F flags */
648- uint32_t flags ;
645+ /* Event object for reacting to events. */
646+ zend_async_event_t event ;
649647 /* The link to the zend_object structure */
650- zend_object * scope_object ;
648+ zend_object * scope_object ;
651649
652650 zend_async_scopes_vector_t scopes ;
653651 zend_async_scope_t * parent_scope ;
@@ -656,25 +654,29 @@ struct _zend_async_scope_s {
656654
657655 zend_async_before_coroutine_enqueue_t before_coroutine_enqueue ;
658656 zend_async_after_coroutine_enqueue_t after_coroutine_enqueue ;
659- zend_async_scope_dispose_t dispose ;
657+ void ( * cancel )( zend_async_scope_t * scope , zend_object * error , bool transfer_error , const bool is_safely ) ;
660658};
661659
662- #define ZEND_ASYNC_SCOPE_F_CLOSED (1u << 0) /* scope was closed */
663- #define ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY (1u << 1) /* scope will not free memory in dispose handler */
664- #define ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY (1u << 2) /* scope will be disposed safely */
660+ #define ZEND_ASYNC_SCOPE_F_CLOSED ZEND_ASYNC_EVENT_F_CLOSED /* scope was closed */
661+ #define ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY ZEND_ASYNC_EVENT_F_NO_FREE_MEMORY /* scope will not free memory in dispose handler */
662+ #define ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY (1u << 14) /* scope will be disposed safely */
663+ #define ZEND_ASYNC_SCOPE_F_CANCELLED (1u << 15) /* scope was cancelled */
664+
665+ #define ZEND_ASYNC_SCOPE_IS_CLOSED (scope ) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_CLOSED) != 0)
666+ #define ZEND_ASYNC_SCOPE_IS_NO_FREE_MEMORY (scope ) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY) != 0)
667+ #define ZEND_ASYNC_SCOPE_IS_DISPOSE_SAFELY (scope ) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY) != 0)
668+ #define ZEND_ASYNC_SCOPE_IS_CANCELLED (scope ) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_CANCELLED) != 0)
665669
666- #define ZEND_ASYNC_SCOPE_IS_CLOSED (scope ) (((scope)->flags & ZEND_ASYNC_SCOPE_F_CLOSED) != 0)
667- #define ZEND_ASYNC_SCOPE_IS_NO_FREE_MEMORY (scope ) (((scope)->flags & ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY) != 0)
668- #define ZEND_ASYNC_SCOPE_IS_DISPOSE_SAFELY (scope ) (((scope)->flags & ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY) != 0)
670+ #define ZEND_ASYNC_SCOPE_SET_CLOSED (scope ) ((scope)->event.flags |= ZEND_ASYNC_SCOPE_F_CLOSED)
671+ #define ZEND_ASYNC_SCOPE_CLR_CLOSED (scope ) ((scope)->event.flags &= ~ZEND_ASYNC_SCOPE_F_CLOSED)
669672
670- #define ZEND_ASYNC_SCOPE_SET_CLOSED (scope ) ((scope)->flags |= ZEND_ASYNC_SCOPE_F_CLOSED )
671- #define ZEND_ASYNC_SCOPE_CLR_CLOSED (scope ) ((scope)->flags &= ~ZEND_ASYNC_SCOPE_F_CLOSED )
673+ #define ZEND_ASYNC_SCOPE_SET_NO_FREE_MEMORY (scope ) ((scope)->event. flags |= ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY )
674+ #define ZEND_ASYNC_SCOPE_CLR_NO_FREE_MEMORY (scope ) ((scope)->event. flags &= ~ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY )
672675
673- #define ZEND_ASYNC_SCOPE_SET_NO_FREE_MEMORY (scope ) ((scope)->flags |= ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY )
674- #define ZEND_ASYNC_SCOPE_CLR_NO_FREE_MEMORY (scope ) ((scope)->flags &= ~ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY )
676+ #define ZEND_ASYNC_SCOPE_SET_DISPOSE_SAFELY (scope ) ((scope)->event. flags |= ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY )
677+ #define ZEND_ASYNC_SCOPE_CLR_DISPOSE_SAFELY (scope ) ((scope)->event. flags &= ~ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY )
675678
676- #define ZEND_ASYNC_SCOPE_SET_DISPOSE (scope ) ((scope)->flags |= ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY)
677- #define ZEND_ASYNC_SCOPE_CLR_DISPOSE (scope ) ((scope)->flags &= ~ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY)
679+ #define ZEND_ASYNC_SCOPE_SET_CANCELLED (scope ) ((scope)->event.flags |= ZEND_ASYNC_SCOPE_F_CANCELLED)
678680
679681static zend_always_inline void
680682zend_async_scope_add_child (zend_async_scope_t * parent_scope , zend_async_scope_t * child_scope )
@@ -862,6 +864,28 @@ static zend_always_inline zend_string *zend_coroutine_callable_name(const zend_c
862864 return zend_string_init ("internal function" , sizeof ("internal function" ) - 1 , 0 );
863865}
864866
867+ /**
868+ * Macro for constructing an FCALL structure from PHP function parameters.
869+ * Z_PARAM_FUNC(fci, fcc);
870+ * Z_PARAM_VARIADIC_WITH_NAMED(args, args_count, named_args);
871+ */
872+ #define ZEND_ASYNC_FCALL_DEFINE (fcall , fci , fcc , args , args_count , named_args ) \
873+ zend_fcall_t * fcall = ecalloc(1, sizeof(zend_fcall_t)); \
874+ fcall->fci = fci; \
875+ fcall->fci_cache = fcc; \
876+ if (args_count) { \
877+ fcall->fci.param_count = args_count; \
878+ fcall->fci.params = safe_emalloc(args_count, sizeof(zval), 0); \
879+ for (uint32_t i = 0; i < args_count; i++) { \
880+ ZVAL_COPY(&fcall->fci.params[i], &args[i]); \
881+ } \
882+ } \
883+ if (named_args) { \
884+ fcall->fci.named_params = named_args; \
885+ GC_ADDREF(named_args); \
886+ } \
887+ Z_TRY_ADDREF(fcall->fci.function_name);
888+
865889///////////////////////////////////////////////////////////////
866890/// Async Context Structures
867891///////////////////////////////////////////////////////////////
0 commit comments