Skip to content

Commit 35d4849

Browse files
committed
Merge branch 'true-async-api' into true-async-api-stable
2 parents 28530c8 + bd76291 commit 35d4849

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

Zend/zend_async_API.c

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ ZEND_API zend_async_event_callback_t * zend_async_event_callback_new(zend_async_
406406
return event_callback;
407407
}
408408

409-
static void coroutine_event_callback_dispose(zend_async_event_callback_t *callback, zend_async_event_t * event);
409+
void coroutine_event_callback_dispose(zend_async_event_callback_t *callback, zend_async_event_t * event);
410410

411411
ZEND_API zend_coroutine_event_callback_t * zend_async_coroutine_callback_new(
412412
zend_coroutine_t * coroutine, zend_async_event_callback_fn callback, size_t size
@@ -537,7 +537,7 @@ ZEND_API void zend_async_waker_destroy(zend_coroutine_t *coroutine)
537537
efree(waker);
538538
}
539539

540-
static void coroutine_event_callback_dispose(zend_async_event_callback_t *callback, zend_async_event_t * event)
540+
void coroutine_event_callback_dispose(zend_async_event_callback_t *callback, zend_async_event_t * event)
541541
{
542542
if (callback->ref_count > 1) {
543543
// If the callback is still referenced, we cannot dispose it yet
@@ -552,14 +552,18 @@ static void coroutine_event_callback_dispose(zend_async_event_callback_t *callba
552552

553553
callback->ref_count = 0;
554554

555-
zend_async_waker_t * waker = ((zend_coroutine_event_callback_t *) callback)->coroutine->waker;
555+
const zend_coroutine_t * coroutine = ((zend_coroutine_event_callback_t *) callback)->coroutine;
556556

557-
if (event != NULL && waker != NULL) {
558-
// remove the event from the waker
559-
zend_hash_index_del(&waker->events, (zend_ulong)event);
557+
if (EXPECTED(coroutine != NULL)) {
558+
zend_async_waker_t * waker = coroutine->waker;
560559

561-
if (waker->triggered_events != NULL) {
562-
zend_hash_index_del(waker->triggered_events, (zend_ulong)event);
560+
if (event != NULL && waker != NULL) {
561+
// remove the event from the waker
562+
zend_hash_index_del(&waker->events, (zend_ulong)event);
563+
564+
if (waker->triggered_events != NULL) {
565+
zend_hash_index_del(waker->triggered_events, (zend_ulong)event);
566+
}
563567
}
564568
}
565569

@@ -582,6 +586,15 @@ ZEND_API void zend_async_waker_add_triggered_event(zend_coroutine_t *coroutine,
582586
}
583587
}
584588

589+
ZEND_API bool zend_async_waker_is_event_exists(zend_coroutine_t *coroutine, zend_async_event_t *event)
590+
{
591+
if (UNEXPECTED(coroutine->waker == NULL)) {
592+
return false;
593+
}
594+
595+
return zend_hash_index_find(&coroutine->waker->events, (zend_ulong)event) != NULL;
596+
}
597+
585598
ZEND_API void zend_async_resume_when(
586599
zend_coroutine_t *coroutine,
587600
zend_async_event_t *event,
@@ -590,6 +603,8 @@ ZEND_API void zend_async_resume_when(
590603
zend_coroutine_event_callback_t *event_callback
591604
)
592605
{
606+
bool locally_allocated_callback = false;
607+
593608
if (UNEXPECTED(ZEND_ASYNC_EVENT_IS_CLOSED(event))) {
594609
zend_throw_error(NULL, "The event cannot be used after it has been terminated");
595610
return;
@@ -610,6 +625,7 @@ ZEND_API void zend_async_resume_when(
610625
event_callback->base.ref_count = 1;
611626
event_callback->base.callback = callback;
612627
event_callback->base.dispose = coroutine_event_callback_dispose;
628+
locally_allocated_callback = true;
613629
}
614630

615631
// Set up the default dispose function if not set
@@ -627,6 +643,10 @@ ZEND_API void zend_async_resume_when(
627643
event->add_callback(event, &event_callback->base);
628644

629645
if (UNEXPECTED(EG(exception) != NULL)) {
646+
if (locally_allocated_callback) {
647+
event_callback->base.dispose(&event_callback->base, event);
648+
}
649+
630650
if (trans_event) {
631651
event->dispose(event);
632652
}
@@ -640,7 +660,18 @@ ZEND_API void zend_async_resume_when(
640660
trigger->callback = &event_callback->base;
641661

642662
if (UNEXPECTED(zend_hash_index_add_ptr(&coroutine->waker->events, (zend_ulong)event, trigger) == NULL)) {
643-
zend_throw_error(NULL, "Failed to add event to the waker");
663+
efree(trigger);
664+
665+
if (locally_allocated_callback) {
666+
event_callback->base.dispose(&event_callback->base, event);
667+
}
668+
669+
if (trans_event) {
670+
event->dispose(event);
671+
}
672+
673+
zend_throw_error(NULL, "Failed to add event to the waker: maybe event already exists");
674+
644675
return;
645676
}
646677
}

Zend/zend_async_API.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
#include "zend_fibers.h"
2020
#include "zend_globals.h"
2121

22-
#define ZEND_ASYNC_API "TrueAsync API v0.2.0"
22+
#define ZEND_ASYNC_API "TrueAsync API v0.3.0"
2323
#define ZEND_ASYNC_API_VERSION_MAJOR 0
24-
#define ZEND_ASYNC_API_VERSION_MINOR 2
24+
#define ZEND_ASYNC_API_VERSION_MINOR 3
2525
#define ZEND_ASYNC_API_VERSION_PATCH 0
2626

2727
#define ZEND_ASYNC_API_VERSION_NUMBER \
@@ -88,6 +88,11 @@ typedef enum {
8888
ZEND_ASYNC_EXEC_MODE_SHELL_EXEC
8989
} zend_async_exec_mode;
9090

91+
typedef enum {
92+
ZEND_COROUTINE_NORMAL = 0,
93+
ZEND_COROUTINE_HI_PRIORITY = 255
94+
} zend_coroutine_priority;
95+
9196
typedef enum
9297
{
9398
ZEND_ASYNC_CLASS_NO = 0,
@@ -334,7 +339,9 @@ typedef void (*zend_async_iterator_method_t)(zend_async_iterator_t *iterator);
334339
/* The maximum number of concurrent tasks that can be executed at the same time */ \
335340
unsigned int concurrency; \
336341
/* Priority for coroutines created by this iterator */ \
337-
int32_t priority;
342+
int32_t priority; \
343+
/* NULLABLE. Exception that stopped the iterator */ \
344+
zend_object * exception;
338345

339346
struct _zend_async_iterator_s {
340347
ZEND_ASYNC_ITERATOR_FIELDS
@@ -381,10 +388,12 @@ struct _zend_async_event_callback_s {
381388
}
382389

383390
#define ZEND_ASYNC_EVENT_CALLBACK_RELEASE(callback) \
384-
if (callback != NULL && callback->ref_count > 1) { \
385-
callback->ref_count--; \
391+
if ((callback) != NULL && (callback)->ref_count > 1) { \
392+
(callback)->ref_count--; \
393+
} else if((callback)->dispose != NULL) { \
394+
(callback)->dispose((callback), NULL); \
386395
} else { \
387-
coroutine_event_callback_dispose(callback, NULL); \
396+
coroutine_event_callback_dispose((callback), NULL); \
388397
}
389398

390399
struct _zend_coroutine_event_callback_s {
@@ -789,11 +798,13 @@ struct _zend_async_scope_s {
789798
#define ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY ZEND_ASYNC_EVENT_F_NO_FREE_MEMORY /* scope will not free memory in dispose handler */
790799
#define ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY (1u << 14) /* scope will be disposed safely */
791800
#define ZEND_ASYNC_SCOPE_F_CANCELLED (1u << 15) /* scope was cancelled */
801+
#define ZEND_ASYNC_SCOPE_F_DISPOSING (1u << 16) /* scope disposing */
792802

793803
#define ZEND_ASYNC_SCOPE_IS_CLOSED(scope) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_CLOSED) != 0)
794804
#define ZEND_ASYNC_SCOPE_IS_NO_FREE_MEMORY(scope) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_NO_FREE_MEMORY) != 0)
795805
#define ZEND_ASYNC_SCOPE_IS_DISPOSE_SAFELY(scope) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_DISPOSE_SAFELY) != 0)
796806
#define ZEND_ASYNC_SCOPE_IS_CANCELLED(scope) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_CANCELLED) != 0)
807+
#define ZEND_ASYNC_SCOPE_IS_DISPOSING(scope) (((scope)->event.flags & ZEND_ASYNC_SCOPE_F_DISPOSING) != 0)
797808

798809
#define ZEND_ASYNC_SCOPE_SET_CLOSED(scope) ((scope)->event.flags |= ZEND_ASYNC_SCOPE_F_CLOSED)
799810
#define ZEND_ASYNC_SCOPE_CLR_CLOSED(scope) ((scope)->event.flags &= ~ZEND_ASYNC_SCOPE_F_CLOSED)
@@ -806,6 +817,9 @@ struct _zend_async_scope_s {
806817

807818
#define ZEND_ASYNC_SCOPE_SET_CANCELLED(scope) ((scope)->event.flags |= ZEND_ASYNC_SCOPE_F_CANCELLED)
808819

820+
#define ZEND_ASYNC_SCOPE_SET_DISPOSING(scope) ((scope)->event.flags |= ZEND_ASYNC_SCOPE_F_DISPOSING)
821+
#define ZEND_ASYNC_SCOPE_CLR_DISPOSING(scope) ((scope)->event.flags &= ~ZEND_ASYNC_SCOPE_F_DISPOSING)
822+
809823
static zend_always_inline void
810824
zend_async_scope_add_child(zend_async_scope_t *parent_scope, zend_async_scope_t *child_scope)
811825
{
@@ -1282,6 +1296,7 @@ ZEND_API zend_async_event_callback_t * zend_async_event_callback_new(zend_async_
12821296
ZEND_API zend_coroutine_event_callback_t * zend_async_coroutine_callback_new(
12831297
zend_coroutine_t * coroutine, zend_async_event_callback_fn callback, size_t size
12841298
);
1299+
ZEND_API void coroutine_event_callback_dispose(zend_async_event_callback_t *callback, zend_async_event_t * event);
12851300

12861301
/* Waker API */
12871302
ZEND_API zend_async_waker_t *zend_async_waker_new(zend_coroutine_t *coroutine);
@@ -1293,6 +1308,7 @@ ZEND_API bool zend_async_waker_apply_error(
12931308
);
12941309
ZEND_API void zend_async_waker_destroy(zend_coroutine_t *coroutine);
12951310
ZEND_API void zend_async_waker_add_triggered_event(zend_coroutine_t *coroutine, zend_async_event_t *event);
1311+
ZEND_API bool zend_async_waker_is_event_exists(zend_coroutine_t *coroutine, zend_async_event_t *event);
12961312

12971313
#define ZEND_ASYNC_WAKER_APPLY_ERROR(waker, error, transfer) zend_async_waker_apply_error((waker), (error), (transfer), true, false)
12981314
#define ZEND_ASYNC_WAKER_APPEND_ERROR(waker, error, transfer) zend_async_waker_apply_error((waker), (error), (transfer), false, false)

0 commit comments

Comments
 (0)