Skip to content

Commit b675f11

Browse files
committed
Merge branch 'true-async-api' into true-async-api-stable
2 parents f99433c + 9645e1e commit b675f11

File tree

5 files changed

+66
-4
lines changed

5 files changed

+66
-4
lines changed

Zend/zend_async_API.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,13 @@ ZEND_API uint32_t zend_coroutine_add_switch_handler(
12831283
return 0;
12841284
}
12851285

1286+
/* Check for duplicate handler */
1287+
for (uint32_t i = 0; i < vector->length; i++) {
1288+
if (vector->data[i].handler == handler) {
1289+
return i;
1290+
}
1291+
}
1292+
12861293
/* Expand array if needed */
12871294
if (vector->length == vector->capacity) {
12881295
vector->capacity = vector->capacity ? vector->capacity * 2 : 4;
@@ -1384,6 +1391,13 @@ ZEND_API void zend_async_add_main_coroutine_start_handler(
13841391
{
13851392
zend_coroutine_switch_handlers_vector_t *vector = &global_main_coroutine_start_handlers;
13861393

1394+
/* Check for duplicate handler */
1395+
for (uint32_t i = 0; i < vector->length; i++) {
1396+
if (vector->data[i].handler == handler) {
1397+
return;
1398+
}
1399+
}
1400+
13871401
/* Expand vector if needed */
13881402
if (vector->length >= vector->capacity) {
13891403
uint32_t new_capacity = vector->capacity ? vector->capacity * 2 : 4;

Zend/zend_async_API.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,26 @@ struct _zend_async_microtask_s {
294294
uint32_t ref_count;
295295
};
296296

297+
#define ZEND_ASYNC_MICROTASK_ADD_REF(microtask) \
298+
do { \
299+
if (microtask != NULL) { \
300+
microtask->ref_count++; \
301+
} \
302+
} while (0)
303+
304+
#define ZEND_ASYNC_MICROTASK_RELEASE(microtask) \
305+
do { \
306+
if (microtask != NULL && microtask->ref_count > 1) { \
307+
microtask->ref_count--; \
308+
} else { \
309+
microtask->ref_count = 0; \
310+
if (microtask->dtor) { \
311+
microtask->dtor(microtask); \
312+
} \
313+
efree(microtask); \
314+
} \
315+
} while (0)
316+
297317
///////////////////////////////////////////////////////////////////
298318
/// Async iterator structures
299319
///////////////////////////////////////////////////////////////////
@@ -561,15 +581,15 @@ static zend_always_inline void
561581
zend_async_callbacks_push(zend_async_event_t *event, zend_async_event_callback_t *callback)
562582
{
563583
if (event->callbacks.data == NULL) {
564-
event->callbacks.data = safe_emalloc(4, sizeof(zend_async_event_callback_t *), 0);
584+
event->callbacks.data = (zend_async_event_callback_t **)safe_emalloc(4, sizeof(zend_async_event_callback_t *), 0);
565585
event->callbacks.capacity = 4;
566586
}
567587

568588
zend_async_callbacks_vector_t *vector = &event->callbacks;
569589

570590
if (vector->length == vector->capacity) {
571591
vector->capacity = vector->capacity ? vector->capacity * 2 : 4;
572-
vector->data = safe_erealloc(vector->data,
592+
vector->data = (zend_async_event_callback_t **)safe_erealloc(vector->data,
573593
vector->capacity,
574594
sizeof(zend_async_event_callback_t *),
575595
0);
@@ -770,13 +790,13 @@ zend_async_scope_add_child(zend_async_scope_t *parent_scope, zend_async_scope_t
770790
child_scope->parent_scope = parent_scope;
771791

772792
if (vector->data == NULL) {
773-
vector->data = safe_emalloc(4, sizeof(zend_async_scope_t *), 0);
793+
vector->data = (zend_async_scope_t **)safe_emalloc(4, sizeof(zend_async_scope_t *), 0);
774794
vector->capacity = 4;
775795
}
776796

777797
if (vector->length == vector->capacity) {
778798
vector->capacity *= 2;
779-
vector->data = safe_erealloc(vector->data, vector->capacity, sizeof(zend_async_scope_t *), 0);
799+
vector->data = (zend_async_scope_t **)safe_erealloc(vector->data, vector->capacity, sizeof(zend_async_scope_t *), 0);
780800
}
781801

782802
vector->data[vector->length++] = child_scope;
@@ -1423,5 +1443,11 @@ END_EXTERN_C()
14231443

14241444
/* Global Main Coroutine Switch Handlers API Macros */
14251445
#define ZEND_ASYNC_ADD_MAIN_COROUTINE_START_HANDLER(handler) zend_async_add_main_coroutine_start_handler(handler)
1446+
#define ZEND_ASYNC_ADD_SWITCH_HANDLER(handler) \
1447+
if (ZEND_ASYNC_CURRENT_COROUTINE) { \
1448+
zend_coroutine_add_switch_handler(ZEND_ASYNC_CURRENT_COROUTINE, handler); \
1449+
} else { \
1450+
zend_async_add_main_coroutine_start_handler(handler); \
1451+
}
14261452

14271453
#endif //ZEND_ASYNC_API_H

Zend/zend_execute_API.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ static void shutdown_destructors_coroutine_dtor(zend_coroutine_t *coroutine)
285285

286286
if (shutdown_context->coroutine == coroutine) {
287287
shutdown_context->coroutine = NULL;
288+
shutdown_context->is_started = false;
288289
zend_error(E_CORE_ERROR, "Shutdown destructors coroutine was not finished property");
289290
EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
290291
shutdown_destructors();
@@ -304,6 +305,12 @@ static bool shutdown_destructors_context_switch_handler(
304305
return false;
305306
}
306307

308+
zend_shutdown_context_t *shutdown_context = &EG(shutdown_context);
309+
310+
if (false == shutdown_context->is_started) {
311+
return false;
312+
}
313+
307314
zend_coroutine_t *shutdown_coroutine = ZEND_ASYNC_SPAWN_WITH_SCOPE_EX(ZEND_ASYNC_MAIN_SCOPE, 1);
308315
shutdown_coroutine->internal_entry = shutdown_destructors_async;
309316
shutdown_coroutine->extended_dispose = shutdown_destructors_coroutine_dtor;
@@ -385,9 +392,12 @@ void shutdown_destructors_async(void) /* {{{ */
385392
}
386393
} zend_catch {
387394
EG(symbol_table).pDestructor = zend_unclean_zval_ptr_dtor;
395+
shutdown_context->is_started = false;
388396
shutdown_destructors();
389397
zend_bailout();
390398
} zend_end_try();
399+
400+
shutdown_context->is_started = false;
391401
}
392402
/* }}} */
393403
#endif

Zend/zend_gc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,11 @@ static void zend_gc_collect_cycles_coroutine(void)
19751975

19761976
ZEND_ASYNC_ADD_MICROTASK(GC_G(microtask));
19771977
zend_gc_collect_cycles();
1978+
1979+
if (GC_G(microtask) != NULL) {
1980+
GC_G(microtask)->is_cancelled = true;
1981+
ZEND_ASYNC_MICROTASK_RELEASE(GC_G(microtask));
1982+
}
19781983
}
19791984

19801985
static zend_string* coroutine_info(zend_async_event_t *event)

Zend/zend_objects_API.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static void store_call_destructors_coroutine_dtor(zend_coroutine_t *coroutine)
7272

7373
if (shutdown_context->coroutine == coroutine) {
7474
shutdown_context->coroutine = NULL;
75+
shutdown_context->is_started = false;
7576
zend_error(E_CORE_ERROR, "Shutdown destructors coroutine was not finished property");
7677
shutdown_destructors();
7778
}
@@ -95,6 +96,12 @@ static bool store_call_destructors_context_switch_handler(
9596
return false;
9697
}
9798

99+
zend_shutdown_context_t *shutdown_context = &EG(shutdown_context);
100+
101+
if (false == shutdown_context->is_started) {
102+
return false;
103+
}
104+
98105
zend_coroutine_t *shutdown_coroutine = ZEND_ASYNC_SPAWN_WITH_SCOPE_EX(ZEND_ASYNC_MAIN_SCOPE, 1);
99106
shutdown_coroutine->internal_entry = store_call_destructors_entry;
100107
shutdown_coroutine->extended_dispose = store_call_destructors_coroutine_dtor;

0 commit comments

Comments
 (0)