mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Add fiber type to better support custom fiber APIs (#7105)
This commit is contained in:
parent
c220c96c37
commit
b76a9dbcf9
2 changed files with 15 additions and 9 deletions
|
@ -199,7 +199,7 @@ static ZEND_NORETURN void zend_fiber_trampoline(transfer_t transfer)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size)
|
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size)
|
||||||
{
|
{
|
||||||
if (UNEXPECTED(!zend_fiber_stack_allocate(&context->stack, stack_size))) {
|
if (UNEXPECTED(!zend_fiber_stack_allocate(&context->stack, stack_size))) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -211,6 +211,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co
|
||||||
context->handle = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
|
context->handle = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
|
||||||
ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL");
|
ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL");
|
||||||
|
|
||||||
|
context->kind = kind;
|
||||||
context->function = coroutine;
|
context->function = coroutine;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -256,7 +257,7 @@ static void zend_fiber_suspend_from(zend_fiber *fiber)
|
||||||
ZEND_ASSERT(fiber->caller && "Fiber has no caller");
|
ZEND_ASSERT(fiber->caller && "Fiber has no caller");
|
||||||
|
|
||||||
zend_fiber_capture_vm_state(&state);
|
zend_fiber_capture_vm_state(&state);
|
||||||
zend_fiber_switch_context(zend_fiber_get_context(fiber->caller));
|
zend_fiber_switch_context(fiber->caller);
|
||||||
zend_fiber_restore_vm_state(&state);
|
zend_fiber_restore_vm_state(&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +268,7 @@ static void zend_fiber_switch_to(zend_fiber *fiber)
|
||||||
|
|
||||||
zend_observer_fiber_switch_notify(EG(current_fiber), context);
|
zend_observer_fiber_switch_notify(EG(current_fiber), context);
|
||||||
|
|
||||||
fiber->caller = zend_fiber_from_context(EG(current_fiber));
|
fiber->caller = EG(current_fiber);
|
||||||
|
|
||||||
zend_fiber_capture_vm_state(&state);
|
zend_fiber_capture_vm_state(&state);
|
||||||
zend_fiber_switch_context(context);
|
zend_fiber_switch_context(context);
|
||||||
|
@ -352,7 +353,7 @@ static ZEND_STACK_ALIGNED zend_fiber_context *zend_fiber_execute(zend_fiber_cont
|
||||||
fiber->execute_data = NULL;
|
fiber->execute_data = NULL;
|
||||||
fiber->stack_bottom = NULL;
|
fiber->stack_bottom = NULL;
|
||||||
|
|
||||||
return zend_fiber_get_context(fiber->caller);
|
return fiber->caller;
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_object *zend_fiber_object_create(zend_class_entry *ce)
|
static zend_object *zend_fiber_object_create(zend_class_entry *ce)
|
||||||
|
@ -451,7 +452,7 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c
|
||||||
fiber->fci.param_count = param_count;
|
fiber->fci.param_count = param_count;
|
||||||
fiber->fci.named_params = named_params;
|
fiber->fci.named_params = named_params;
|
||||||
|
|
||||||
if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_fiber_execute, EG(fiber_stack_size))) {
|
if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +482,7 @@ ZEND_METHOD(Fiber, start)
|
||||||
|
|
||||||
ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
|
ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
|
||||||
{
|
{
|
||||||
if (UNEXPECTED(EG(current_fiber) == EG(main_fiber))) {
|
if (UNEXPECTED(EG(current_fiber)->kind != zend_ce_fiber)) {
|
||||||
zend_throw_error(zend_ce_fiber_error, "Cannot suspend outside of a fiber");
|
zend_throw_error(zend_ce_fiber_error, "Cannot suspend outside of a fiber");
|
||||||
RETURN_THROWS();
|
RETURN_THROWS();
|
||||||
}
|
}
|
||||||
|
@ -692,7 +693,7 @@ ZEND_METHOD(Fiber, this)
|
||||||
{
|
{
|
||||||
ZEND_PARSE_PARAMETERS_NONE();
|
ZEND_PARSE_PARAMETERS_NONE();
|
||||||
|
|
||||||
if (EG(current_fiber) == EG(main_fiber)) {
|
if (EG(current_fiber)->kind != zend_ce_fiber) {
|
||||||
RETURN_NULL();
|
RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,10 @@ typedef zend_fiber_context *(*zend_fiber_coroutine)(zend_fiber_context *context)
|
||||||
|
|
||||||
/* Defined as a macro to allow anonymous embedding. */
|
/* Defined as a macro to allow anonymous embedding. */
|
||||||
#define ZEND_FIBER_CONTEXT_FIELDS \
|
#define ZEND_FIBER_CONTEXT_FIELDS \
|
||||||
|
/* Handle to fiber state as needed by boost.context */ \
|
||||||
void *handle; \
|
void *handle; \
|
||||||
|
/* Pointer that identifies the fiber type. */ \
|
||||||
|
void *kind; \
|
||||||
zend_fiber_coroutine function; \
|
zend_fiber_coroutine function; \
|
||||||
zend_fiber_stack stack; \
|
zend_fiber_stack stack; \
|
||||||
zend_fiber_status status; \
|
zend_fiber_status status; \
|
||||||
|
@ -98,7 +101,7 @@ struct _zend_fiber {
|
||||||
zend_object std;
|
zend_object std;
|
||||||
|
|
||||||
/* Fiber that resumed us. */
|
/* Fiber that resumed us. */
|
||||||
zend_fiber *caller;
|
zend_fiber_context *caller;
|
||||||
|
|
||||||
/* Fiber context fields (embedded to avoid memory allocation). */
|
/* Fiber context fields (embedded to avoid memory allocation). */
|
||||||
ZEND_FIBER_CONTEXT_FIELDS;
|
ZEND_FIBER_CONTEXT_FIELDS;
|
||||||
|
@ -128,7 +131,7 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val
|
||||||
ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_value);
|
ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_value);
|
||||||
|
|
||||||
/* These functions may be used to create custom fibers (coroutines) using the bundled fiber switching context. */
|
/* These functions may be used to create custom fibers (coroutines) using the bundled fiber switching context. */
|
||||||
ZEND_API zend_bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size);
|
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size);
|
||||||
ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context);
|
ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context);
|
||||||
ZEND_API void zend_fiber_switch_context(zend_fiber_context *to);
|
ZEND_API void zend_fiber_switch_context(zend_fiber_context *to);
|
||||||
|
|
||||||
|
@ -136,6 +139,8 @@ END_EXTERN_C()
|
||||||
|
|
||||||
static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context)
|
static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context)
|
||||||
{
|
{
|
||||||
|
ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber");
|
||||||
|
|
||||||
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
|
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue