Skip to content

Commit 077b2c6

Browse files
committed
Merge branch 'true-async-api' into true-async-api-stable
2 parents 35d4849 + 6b98adb commit 077b2c6

File tree

2 files changed

+91
-11
lines changed

2 files changed

+91
-11
lines changed

Zend/zend_fibers.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "zend_generators.h"
3333

3434
#include "zend_fibers.h"
35+
36+
#include "zend_async_API.h"
3537
#include "zend_fibers_arginfo.h"
3638

3739
#ifdef HAVE_VALGRIND
@@ -562,6 +564,19 @@ static void zend_fiber_cleanup(zend_fiber_context *context)
562564
fiber->caller = NULL;
563565
}
564566

567+
#ifdef PHP_ASYNC_API
568+
static zend_always_inline bool can_use_fiber(void)
569+
{
570+
if (UNEXPECTED(ZEND_ASYNC_IS_ACTIVE)) {
571+
zend_throw_error(zend_ce_fiber_error, "Cannot create a fiber while an True Async is active");
572+
return false;
573+
}
574+
575+
ZEND_ASYNC_DEACTIVATE;
576+
return true;
577+
}
578+
#endif
579+
565580
static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
566581
{
567582
ZEND_ASSERT(Z_TYPE(transfer->value) == IS_NULL && "Initial transfer value to fiber context must be NULL");
@@ -711,6 +726,12 @@ ZEND_API zend_result zend_fiber_start(zend_fiber *fiber, zval *return_value)
711726
{
712727
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_INIT);
713728

729+
#ifdef PHP_ASYNC_API
730+
if (UNEXPECTED(false == can_use_fiber())) {
731+
return FAILURE;
732+
}
733+
#endif
734+
714735
if (zend_fiber_init_context(&fiber->context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size)) == FAILURE) {
715736
return FAILURE;
716737
}
@@ -726,6 +747,12 @@ ZEND_API zend_result zend_fiber_start(zend_fiber *fiber, zval *return_value)
726747

727748
ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_value)
728749
{
750+
#ifdef PHP_ASYNC_API
751+
if (UNEXPECTED(false == can_use_fiber())) {
752+
return;
753+
}
754+
#endif
755+
729756
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
730757

731758
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
@@ -737,6 +764,12 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val
737764

738765
ZEND_API void zend_fiber_resume_exception(zend_fiber *fiber, zval *exception, zval *return_value)
739766
{
767+
#ifdef PHP_ASYNC_API
768+
if (UNEXPECTED(false == can_use_fiber())) {
769+
return;
770+
}
771+
#endif
772+
740773
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
741774

742775
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
@@ -748,6 +781,12 @@ ZEND_API void zend_fiber_resume_exception(zend_fiber *fiber, zval *exception, zv
748781

749782
ZEND_API void zend_fiber_suspend(zend_fiber *fiber, zval *value, zval *return_value)
750783
{
784+
#ifdef PHP_ASYNC_API
785+
if (UNEXPECTED(false == can_use_fiber())) {
786+
return;
787+
}
788+
#endif
789+
751790
fiber->stack_bottom->prev_execute_data = NULL;
752791

753792
zend_fiber_transfer transfer = zend_fiber_suspend_internal(fiber, value);
@@ -876,6 +915,12 @@ ZEND_METHOD(Fiber, __construct)
876915
Z_PARAM_FUNC(fci, fcc)
877916
ZEND_PARSE_PARAMETERS_END();
878917

918+
#ifdef PHP_ASYNC_API
919+
if (UNEXPECTED(false == can_use_fiber())) {
920+
RETURN_THROWS();
921+
}
922+
#endif
923+
879924
zend_fiber *fiber = (zend_fiber *) Z_OBJ_P(ZEND_THIS);
880925

881926
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_INIT || Z_TYPE(fiber->fci.function_name) != IS_UNDEF)) {
@@ -898,6 +943,12 @@ ZEND_METHOD(Fiber, start)
898943
Z_PARAM_VARIADIC_WITH_NAMED(fiber->fci.params, fiber->fci.param_count, fiber->fci.named_params);
899944
ZEND_PARSE_PARAMETERS_END();
900945

946+
#ifdef PHP_ASYNC_API
947+
if (UNEXPECTED(false == can_use_fiber())) {
948+
RETURN_THROWS();
949+
}
950+
#endif
951+
901952
if (UNEXPECTED(zend_fiber_switch_blocked())) {
902953
zend_throw_error(zend_ce_fiber_error, "Cannot switch fibers in current execution context");
903954
RETURN_THROWS();

Zend/zend_gc.c

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,11 +2176,21 @@ ZEND_API int zend_gc_collect_cycles(void)
21762176
return 0;
21772177
}
21782178

2179+
const bool in_fiber = EG(active_fiber) != NULL;
2180+
21792181
//
21802182
// We might enter this context from different coroutines, so we don’t initialize anything here.
21812183
//
2182-
gc_async_context_t *context = &GC_G(async_context);
2183-
gc_stack *stack = GC_G(gc_stack);
2184+
gc_async_context_t *context = NULL;
2185+
gc_stack *stack = NULL;
2186+
2187+
if (in_fiber) {
2188+
context = ecalloc(1, sizeof(gc_async_context_t));
2189+
stack = emalloc(sizeof(gc_stack));
2190+
} else {
2191+
context = &GC_G(async_context);
2192+
stack = GC_G(gc_stack);
2193+
}
21842194

21852195
if (UNEXPECTED(context->state == GC_ASYNC_STATE_CONTINUE)) {
21862196
// If we reach this point, it means the destructor call was interrupted by a suspend() operation,
@@ -2197,14 +2207,21 @@ ZEND_API int zend_gc_collect_cycles(void)
21972207
context->should_rerun_gc = 0;
21982208
context->did_rerun_gc = 0;
21992209
context->gc_flags = 0;
2210+
// reset the destructor index
2211+
GC_G(dtor_idx) = GC_FIRST_ROOT;
22002212

2201-
if (GC_G(gc_stack) == NULL) {
2202-
stack = ecalloc(1, sizeof(gc_stack));
2213+
if (false == in_fiber) {
2214+
if (GC_G(gc_stack) == NULL) {
2215+
stack = emalloc(sizeof(gc_stack));
2216+
stack->prev = NULL;
2217+
stack->next = NULL;
2218+
GC_G(gc_stack) = stack;
2219+
} else {
2220+
stack = GC_G(gc_stack);
2221+
}
2222+
} else {
22032223
stack->prev = NULL;
22042224
stack->next = NULL;
2205-
GC_G(gc_stack) = stack;
2206-
} else {
2207-
stack = GC_G(gc_stack);
22082225
}
22092226
}
22102227

@@ -2248,6 +2265,8 @@ ZEND_API int zend_gc_collect_cycles(void)
22482265
stack.next = NULL;
22492266
#endif
22502267

2268+
end = 0;
2269+
22512270
if (GC_G(gc_active)) {
22522271
GC_G(collector_time) += zend_hrtime() - GC_COLLECT_START_TIME;
22532272
GC_COLLECT_FINISH_0;
@@ -2357,7 +2376,9 @@ ZEND_API int zend_gc_collect_cycles(void)
23572376
gc_stack_free(GC_COLLECT_STACK);
23582377

23592378
#ifdef PHP_ASYNC_API
2360-
end = GC_G(first_unused);
2379+
if (false == in_fiber) {
2380+
end = GC_G(first_unused);
2381+
}
23612382
#endif
23622383

23632384
/* Destroy zvals. The root buffer may be reallocated. */
@@ -2442,9 +2463,17 @@ ZEND_API int zend_gc_collect_cycles(void)
24422463

24432464
GC_G(collector_time) += zend_hrtime() - GC_COLLECT_START_TIME;
24442465
#ifdef PHP_ASYNC_API
2445-
GC_G(async_context).state = GC_ASYNC_STATE_NONE;
2446-
if (GC_G(gc_stack) != NULL) {
2447-
GC_COLLECT_FREE_STACK;
2466+
if (in_fiber) {
2467+
const int total_count = GC_COLLECT_TOTAL_COUNT;
2468+
efree(context);
2469+
efree(stack);
2470+
return total_count;
2471+
} else {
2472+
GC_G(async_context).state = GC_ASYNC_STATE_NONE;
2473+
if (GC_G(gc_stack) != NULL) {
2474+
GC_G(gc_stack) = NULL;
2475+
efree(stack);
2476+
}
24482477
}
24492478
#endif
24502479
return GC_COLLECT_TOTAL_COUNT;

0 commit comments

Comments
 (0)