Skip to content

Instantly share code, notes, and snippets.

Created October 15, 2015 23:01
Show Gist options
  • Save anonymous/b1d6a389e254a2587541 to your computer and use it in GitHub Desktop.
Save anonymous/b1d6a389e254a2587541 to your computer and use it in GitHub Desktop.
Coroutine example usage in PHP
#!/usr/bin/env php
<?php
class Task
{
protected $taskId;
protected $coroutine;
protected $sendValue = null;
protected $beforeFirstYield = true;
public function __construct($taskId, \Generator $coroutine)
{
$this->taskId = $taskId;
$this->coroutine = $coroutine;
}
public function getTaskId()
{
return $this->taskId;
}
public function setSendValue($sendValue)
{
$this->sendValue = $sendValue;
}
public function run()
{
if (!$this->beforeFirstYield) {
$retval = $this->coroutine->send($this->sendValue);
$this->sendValue = null;
return $retval;
}
$this->beforeFirstYield = false;
$current = $this->coroutine->current();
return $current;
}
public function isFinished()
{
return !$this->coroutine->valid();
}
}
class Scheduler
{
protected $index = 0;
protected $taskMap = [];
protected $taskQueue;
protected $msgs = [];
public function __construct()
{
$this->taskQueue = new \SplQueue();
}
public function newTask(\Generator $coroutine, $msg = null)
{
$taskId = ++$this->index;
$task = new \Task($taskId, $coroutine);
$this->schedule($task);
$this->taskMap[$taskId] = $task;
$this->msgs[$taskId] = $msg;
return $taskId;
}
public function schedule(Task $task)
{
$this->taskQueue->enqueue($task);
}
public function run()
{
while (!$this->taskQueue->isEmpty()) {
$task = $this->taskQueue->dequeue();
$task->setSendValue($this->msgs[$task->getTaskId()]);
$task->run();
if ($task->isFinished()) {
unset($this->taskMap[$task->getTaskId()]);
continue;
}
$this->schedule($task);
}
}
}
function task1()
{
for ($i = 1; $i <= 10; ++$i) {
echo yield. ">iteration $i.\n";
}
}
function task2()
{
for ($i = 1; $i <= 9; ++$i) {
echo yield.">iteration $i.\n";
}
}
function task3()
{
for ($i = 1; $i <= 8; ++$i) {
echo yield.">iteration $i.\n";
}
}
function task4()
{
for ($i = 1; $i <= 7; ++$i) {
echo yield.">iteration $i.\n";
}
}
function task5()
{
for ($i = 1; $i <= 6; ++$i) {
echo yield.">iteration $i.\n";
}
}
$task1 = task1();
$task2 = task2();
$task3 = task3();
$task4 = task4();
$task5 = task5();
$scheduler = new Scheduler;
$scheduler->newTask($task1, 'TASK1');
$scheduler->newTask($task2, 'TASK2');
$scheduler->newTask($task3, 'TASK3');
$scheduler->newTask($task5, 'TASK5');
$scheduler->newTask($task4, 'TASK4');
$scheduler->run();
//exit;
//Coroutines
function coroutine1()
{
for ($i=0; $i<9999; $i++) {
yield $i => yield;
}
}
function coroutine2()
{
for ($i=0; $i<9999; $i++) {
yield 1;
yield 2;
}
}
$coroutine1 = coroutine1();
$coroutine2 = coroutine2();
echo "coroutine1 -- example \n";
$coroutine1->send('foo'); //its returns 'foo'
var_dump(
[
'valid' => $coroutine1->valid(),
'key' => $coroutine1->key(),
'value' => $coroutine1->current(),
]
);
echo "coroutine2 -- example \n";
var_dump(
[
'valid' => $coroutine2->valid(),
'current' => $coroutine2->current(),
]
);
$coroutine2->next();
var_dump(
['next' => $coroutine2->current()]
);
exit;
//SqlQueue Example
$q = new SplQueue();
$q->setIteratorMode(SplDoublyLinkedList::IT_MODE_KEEP); //have two modes available: keep and delete
$q->enqueue('item 1');
$q->enqueue('item 2');
$q->enqueue('item 3');
$q->dequeue(); //dequeue Item 1
//$q->dequeue();
//$q->dequeue();
foreach ($q as $item) {
echo $item ."\n";
}
$q->enqueue('item 4');
foreach ($q as $item) {
echo $item ."\n";
}
// Pros
// -- Coroutines can be used as state machine
// -- With coroutines you can write concurrent applications with cooperative MultiTasking
// -- With coroutines you can write assync/non-blocking IO applications
// Cons
// -- You can't managing memory without a JIT Compiler
// -- You can't apply Preemptive MultiTasking
//Reference
// http://sysmagazine.com/posts/164173/
// http://gnugat.github.io/2014/04/30/php-generators-and-coroutines.html
// http://eli.thegreenplace.net/2009/08/29/co-routines-as-an-alternative-to-state-machines/
// http://nikic.github.io/2012/12/22/Cooperative-multitasking-using-coroutines-in-PHP.html
// http://php.net/manual/en
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment