Hi Edmond,

First of all, sorry for my bad English, and thanks a lot for the huge amount of work you’ve put into this proposal. You researched, wrote the RFC, implemented it, and answered tons of questions. Really impressive.

I have one suggestion and two small questions.

*Suggestion:*

Maybe keep the base /Awaitable/ internal and expose two userland interfaces that match the two cases described in the RFC:
|
// Single state change, idempotent read, same result on each await
interface Future extends Awaitable {}

// Multiple state changes, each await may observe a new state
interface Streamable extends Awaitable {}
This makes the single-shot vs multi-shot difference explicit and easier for tools and libraries to reason about.
|
*Questions (self-cancellation)*

1. What happens here?

|use function Async\spawn;
use function Async\suspend;

$coroutine = spawn(function() use (&$coroutine) {
    $coroutine->cancel(new \Async\CancellationError("Self-cancelled"));
    echo "Before suspend\n";
    suspend();
    echo "After suspend\n"; // should this run?
    return "completed";
});

|

|await($coroutine);|

Can a cancelled coroutine suspend?
And if a function that yields is called after the cancel, should that suspension still happen?

2. And what about this one?

|use function Async\spawn;

$coroutine2 = spawn(function() use (&$coroutine2) {
    $coroutine2->cancel(new \Async\CancellationError("Self-cancelled"));
    echo "Before exception\n";
    throw new \RuntimeException("boom after cancel");
});

|

|await($coroutine2);|

Which error does await() throw in this case — CancellationError or RuntimeException?

It’d be great to clarify that in the docs, since it affects where people put cleanup, logging, etc.


Again, thanks for the work, especially on such an important feature for PHP’s future.
Hope to see it in php-src soon.


Best,
Luís Vinícius

On Thu, 30 Oct 2025 08:19:40 +0000, Edmond Dantes wrote:

> Hi
>
> 1.5 RFC:
> https://wiki.php.net/rfc/true_async
>
> Here’s the fifth version of the RFC with the updates made after the
> 1.4 discussion.
>
> Starting from 2025-11-03, there will be a two-week discussion period.
>
> **Changelog:**
>
> * Added FutureLike interface methods: cancel(), isCompleted(), isCancelled()
> * Renamed Coroutine::isFinished() to Coroutine::isCompleted()
> * Clarified exit/die behavior: always triggers Graceful Shutdown mode
> regardless of where called
> * Added rationale for “Cancellable by design” policy: explains why
> default cancellability reduces code complexity for read-heavy PHP
> workloads
> * RFC structure improvements: reorganized Cancellation section with
> proper subsections hierarchy
> * Moved “Coroutine lifetime” as subsection under Coroutine section
> * Extended glossary with Awaitable, Suspension, Graceful Shutdown, and
> Deadlock terms
> * Introduced FutureLike interface with single-assignment semantics and
> changed await() signature to accept FutureLike instead of Awaitable
> for type safety
> * Split RFC: Moved Scope and structured concurrency functionality to
> separate Scope RFC. Base RFC now focuses on core async primitives
> (coroutines, await, cancellation)
>
> I decided not to wait until Monday and made the changes today. If
> anyone has read version 1.4 and has comments on it, they’re still
> relevant.
>
> The Scope API has been moved to a separate RFC:
> https://wiki.php.net/rfc/true_async_scope
>
> ----
> Best Regards, Ed

Reply via email to