Skip to content

Instantly share code, notes, and snippets.

@diloabininyeri
Created January 10, 2024 08:51
Show Gist options
  • Save diloabininyeri/0f2c28a4c2b91ff1a0d34ea128dd9086 to your computer and use it in GitHub Desktop.
Save diloabininyeri/0f2c28a4c2b91ff1a0d34ea128dd9086 to your computer and use it in GitHub Desktop.
php async promise
class Parallel
{
private array $threads = [];
private array $process = [];
public function add(PromiseInterface $promise): self
{
$this->threads[] = $promise;
return $this;
}
public function run(): void
{
foreach ($this->threads as $thread) {
$descriptors = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'], // stderr
];
$process = proc_open('php', $descriptors, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], $this->generatePhpCode($thread));
fclose($pipes[0]);
fclose($pipes[2]);
$this->process [] = [
'pipe' => $pipes[1],
'process' => $process,
'thread' => $thread
];
}
}
}
/***
* @return void
*/
public function wait(): void
{
while (!empty($this->process)) {
foreach ($this->process as $key => $value) {
[
'pipe' => $pipe,
'process' => $process,
'thread' => $thread
] = $value;
if (is_resource($process)) {
$status = proc_get_status($process);
if ($status['running']) {
continue;
}
/**
* @var PromiseInterface $thread
*/
$thread->then(stream_get_contents($pipe));
echo PHP_EOL;
proc_close($process);
unset($this->process[$key]);
}
}
}
}
/***
* @param PromiseInterface $promise
* @return string
*/
private function generatePhpCode(PromiseInterface $promise): string
{
$serialize=serialize($promise);
return "<?php require_once 'vendor/autoload.php';\$closure = unserialize('$serialize');echo \$closure(); ?>";
}
}
interface PromiseInterface
{
public function then(mixed $value);
public function __invoke();
}
readonly class PromiseOne implements PromiseInterface
{
public function __construct(private int $id)
{
}
#[\Override]
public function then(mixed $value)
{
echo $value;
}
public function __invoke()
{
sleep(1);
return $this->id;
}
}
$parallel = new parallel();
$parallel
->add(new PromiseOne(1))
->add(new PromiseOne(2))
->add(new PromiseOne(3))
->add(new PromiseOne(4))
->add(new PromiseOne(5))
->add(new PromiseOne(6))
->add(new PromiseOne(7))
->add(new PromiseOne(8));
$parallel->run();
$parallel->wait();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment