```php
use Async\spawn;
use Async\Channel;
function worker(Channel $tasks) {
// Start a process for this coroutine
$proc = proc_open("php worker.php", [
["pipe","r"],
["pipe","w"],
["pipe","w"]
], $pipes);
$stdin = $pipes[0];
$stdout = $pipes[1];
while (true) {
// Receive a task (this suspends the coroutine)
$task = $tasks->recv();
// Write task to process (suspends while writing)
fwrite($stdin, $task . "\n");
// Read result (suspends while waiting for data)
$result = fgets($stdout);
... make some else
}
}
$tasks = new Channel();
// Start N workers
for ($i = 0; $i < 10; $i++) {
spawn(worker(...), $tasks);
}
// Producer...
$tasks->push(...);
$tasks->push(...);
$tasks->push(...);
// Close Channel auto after leave function
```
Please look at this code.
There are three or five other ways to implement it. And most of them
would likely be worse in terms of reliability. Because in this example
there is almost no asynchronous code at all. Everything is sequential.
There is no synchronization. There is nothing. Just a channel and just
coroutines. That is all. And inside each coroutine the code is
synchronous.
And you do not even need any structural concurrency. The task is
solved because when the channel is destroyed, an exception is thrown
and the coroutines will terminate together with the rest of the code.
Of course, if you add automatic process restart, it becomes a bit more
complex, but the code is still synchronous. Which is very good.
Imagine a person who has never worked with async before. How hard
would it be for them to write this code?
---
Ed