On 07/03/2025 09:24, Edmond Dantes wrote:
Now, imagine a case where we need to create a coroutine not tied to
the parent.
To do this, we have to define a separate function or syntax.
Such a coroutine is created to perform an action that must be completed,
even if the parent coroutines are not fully executed.
Typically, this is a critical action, like logging or sending a
notification.
This leads to an issue:
* Ordinary actions use a function that the programmer always remembers.
* Important actions require a separate function, which the programmer
might forget.
Let's assume we want to support this scenario; we could:
a) Throw away all automatic resource management, and make it the user's
responsibility to arrange for additional fibers to be cancelled when
their "parent" is cancelled
b) Create unmanaged fibers by default, but provide a simple mechanism to
"attach" to a child/parent
c) Provide automatic cleanup by default, but a simple mechanism to
"disown" a child/parent (similar to Unix processes)
d) Provide two separate-but-equal primitives for spawning coroutines,
"run as child", and "run as top-level"
Option (a) feels rather unappealing; it also implies that no "parent"
relationship is available for things like context data.
I think you agree that top-level fibers would be the less common case,
so (b) seems awkward as well.
Option (c) might look like this:
async {
$child = asyncRun foo();
$bgTask = asyncRun bar();
$bgTask->detach();
}
// foo() guaranteed to be completed or cancelled, bar() continuing as an
independent fiber
Or maybe the detach would be inside bar(), e.g.
Fiber::getCurrent()->detach()
Option (d) might look like this:
async {
$child = asyncChild foo();
$bgTask = asyncDetached bar();
}
// foo() guaranteed to be completed or cancelled, bar() continuing as an
independent fiber
(all names and syntax picked for fast illustration, not an exact proposal)
--
Rowan Tommins
[IMSoP]