Expose fibers API

This commit is contained in:
Arnaud Le Blanc 2024-02-21 16:32:58 +01:00
parent 6b037200a4
commit 7c6ff87869
No known key found for this signature in database
GPG key ID: 0098C05DD15ABC13

View file

@ -20,6 +20,7 @@
#include "zend.h"
#include "zend_API.h"
#include "zend_ini.h"
#include "zend_variables.h"
#include "zend_vm.h"
#include "zend_exceptions.h"
#include "zend_builtin_functions.h"
@ -637,7 +638,11 @@ static zend_always_inline void zend_fiber_delegate_transfer_result(
RETURN_THROWS();
}
RETURN_COPY_VALUE(&transfer->value);
if (return_value != NULL) {
RETURN_COPY_VALUE(&transfer->value);
} else {
zval_ptr_dtor(&transfer->value);
}
}
static zend_always_inline zend_fiber_transfer zend_fiber_switch_to(
@ -665,7 +670,7 @@ static zend_always_inline zend_fiber_transfer zend_fiber_switch_to(
return transfer;
}
static zend_always_inline zend_fiber_transfer zend_fiber_resume(zend_fiber *fiber, zval *value, bool exception)
static zend_always_inline zend_fiber_transfer zend_fiber_resume_internal(zend_fiber *fiber, zval *value, bool exception)
{
zend_fiber *previous = EG(active_fiber);
@ -683,8 +688,10 @@ static zend_always_inline zend_fiber_transfer zend_fiber_resume(zend_fiber *fibe
return transfer;
}
static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fiber, zval *value)
static zend_always_inline zend_fiber_transfer zend_fiber_suspend_internal(zend_fiber *fiber, zval *value)
{
ZEND_ASSERT(!(fiber->flags & ZEND_FIBER_FLAG_DESTROYED));
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED);
ZEND_ASSERT(fiber->caller != NULL);
zend_fiber_context *caller = fiber->caller;
@ -695,6 +702,54 @@ static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fib
return zend_fiber_switch_to(caller, value, false);
}
ZEND_API zend_result zend_fiber_start(zend_fiber *fiber, zval *return_value)
{
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_INIT);
if (zend_fiber_init_context(&fiber->context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size)) == FAILURE) {
return FAILURE;
}
fiber->previous = &fiber->context;
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, NULL, false);
zend_fiber_delegate_transfer_result(&transfer, EG(current_execute_data), return_value);
return SUCCESS;
}
ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_value)
{
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, value, /* exception */ false);
zend_fiber_delegate_transfer_result(&transfer, EG(current_execute_data), return_value);
}
ZEND_API void zend_fiber_resume_exception(zend_fiber *fiber, zval *exception, zval *return_value)
{
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, exception, /* exception */ true);
zend_fiber_delegate_transfer_result(&transfer, EG(current_execute_data), return_value);
}
ZEND_API void zend_fiber_suspend(zend_fiber *fiber, zval *value, zval *return_value)
{
fiber->stack_bottom->prev_execute_data = NULL;
zend_fiber_transfer transfer = zend_fiber_suspend_internal(fiber, value);
zend_fiber_delegate_transfer_result(&transfer, EG(current_execute_data), return_value);
}
static zend_object *zend_fiber_object_create(zend_class_entry *ce)
{
zend_fiber *fiber = emalloc(sizeof(zend_fiber));
@ -720,7 +775,7 @@ static void zend_fiber_object_destroy(zend_object *object)
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
zend_fiber_transfer transfer = zend_fiber_resume(fiber, &graceful_exit, true);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, &graceful_exit, true);
zval_ptr_dtor(&graceful_exit);
@ -836,7 +891,7 @@ ZEND_METHOD(Fiber, start)
fiber->previous = &fiber->context;
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, NULL, false);
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
@ -871,7 +926,7 @@ ZEND_METHOD(Fiber, suspend)
fiber->stack_bottom->prev_execute_data = NULL;
zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);
zend_fiber_transfer transfer = zend_fiber_suspend_internal(fiber, value);
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
@ -900,7 +955,7 @@ ZEND_METHOD(Fiber, resume)
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
zend_fiber_transfer transfer = zend_fiber_resume(fiber, value, false);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, value, false);
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
@ -928,7 +983,7 @@ ZEND_METHOD(Fiber, throw)
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
zend_fiber_transfer transfer = zend_fiber_resume(fiber, exception, true);
zend_fiber_transfer transfer = zend_fiber_resume_internal(fiber, exception, true);
zend_fiber_delegate_transfer_result(&transfer, INTERNAL_FUNCTION_PARAM_PASSTHRU);
}