Skip to content

Commit b76a9db

Browse files
authored
Add fiber type to better support custom fiber APIs (#7105)
1 parent c220c96 commit b76a9db

File tree

2 files changed

+15
-9
lines changed

2 files changed

+15
-9
lines changed

Zend/zend_fibers.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ static ZEND_NORETURN void zend_fiber_trampoline(transfer_t transfer)
199199
abort();
200200
}
201201

202-
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size)
202+
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size)
203203
{
204204
if (UNEXPECTED(!zend_fiber_stack_allocate(&context->stack, stack_size))) {
205205
return false;
@@ -211,6 +211,7 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co
211211
context->handle = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
212212
ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL");
213213

214+
context->kind = kind;
214215
context->function = coroutine;
215216

216217
return true;
@@ -256,7 +257,7 @@ static void zend_fiber_suspend_from(zend_fiber *fiber)
256257
ZEND_ASSERT(fiber->caller && "Fiber has no caller");
257258

258259
zend_fiber_capture_vm_state(&state);
259-
zend_fiber_switch_context(zend_fiber_get_context(fiber->caller));
260+
zend_fiber_switch_context(fiber->caller);
260261
zend_fiber_restore_vm_state(&state);
261262
}
262263

@@ -267,7 +268,7 @@ static void zend_fiber_switch_to(zend_fiber *fiber)
267268

268269
zend_observer_fiber_switch_notify(EG(current_fiber), context);
269270

270-
fiber->caller = zend_fiber_from_context(EG(current_fiber));
271+
fiber->caller = EG(current_fiber);
271272

272273
zend_fiber_capture_vm_state(&state);
273274
zend_fiber_switch_context(context);
@@ -352,7 +353,7 @@ static ZEND_STACK_ALIGNED zend_fiber_context *zend_fiber_execute(zend_fiber_cont
352353
fiber->execute_data = NULL;
353354
fiber->stack_bottom = NULL;
354355

355-
return zend_fiber_get_context(fiber->caller);
356+
return fiber->caller;
356357
}
357358

358359
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
451452
fiber->fci.param_count = param_count;
452453
fiber->fci.named_params = named_params;
453454

454-
if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_fiber_execute, EG(fiber_stack_size))) {
455+
if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
455456
RETURN_THROWS();
456457
}
457458

@@ -481,7 +482,7 @@ ZEND_METHOD(Fiber, start)
481482

482483
ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
483484
{
484-
if (UNEXPECTED(EG(current_fiber) == EG(main_fiber))) {
485+
if (UNEXPECTED(EG(current_fiber)->kind != zend_ce_fiber)) {
485486
zend_throw_error(zend_ce_fiber_error, "Cannot suspend outside of a fiber");
486487
RETURN_THROWS();
487488
}
@@ -692,7 +693,7 @@ ZEND_METHOD(Fiber, this)
692693
{
693694
ZEND_PARSE_PARAMETERS_NONE();
694695

695-
if (EG(current_fiber) == EG(main_fiber)) {
696+
if (EG(current_fiber)->kind != zend_ce_fiber) {
696697
RETURN_NULL();
697698
}
698699

Zend/zend_fibers.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ typedef zend_fiber_context *(*zend_fiber_coroutine)(zend_fiber_context *context)
7272

7373
/* Defined as a macro to allow anonymous embedding. */
7474
#define ZEND_FIBER_CONTEXT_FIELDS \
75+
/* Handle to fiber state as needed by boost.context */ \
7576
void *handle; \
77+
/* Pointer that identifies the fiber type. */ \
78+
void *kind; \
7679
zend_fiber_coroutine function; \
7780
zend_fiber_stack stack; \
7881
zend_fiber_status status; \
@@ -98,7 +101,7 @@ struct _zend_fiber {
98101
zend_object std;
99102

100103
/* Fiber that resumed us. */
101-
zend_fiber *caller;
104+
zend_fiber_context *caller;
102105

103106
/* Fiber context fields (embedded to avoid memory allocation). */
104107
ZEND_FIBER_CONTEXT_FIELDS;
@@ -128,14 +131,16 @@ ZEND_API void zend_fiber_resume(zend_fiber *fiber, zval *value, zval *return_val
128131
ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_value);
129132

130133
/* These functions may be used to create custom fibers (coroutines) using the bundled fiber switching context. */
131-
ZEND_API zend_bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size);
134+
ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, void *kind, zend_fiber_coroutine coroutine, size_t stack_size);
132135
ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context);
133136
ZEND_API void zend_fiber_switch_context(zend_fiber_context *to);
134137

135138
END_EXTERN_C()
136139

137140
static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context)
138141
{
142+
ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber");
143+
139144
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
140145
}
141146

0 commit comments

Comments
 (0)