A taskstack generator stack is used in the following code to implement the synchronous writing of the asynchronous method Swoole_timer_after, and the invocation of the child generator is implemented incidentally;
as long as there is an asynchronous operation with the callback method, Can be used to implement the synchronous writing of asynchronous operation;
Class Taskstack {public $stack;
Public $generator;
Public $return;
Public function __construct (generator $generator) {$this->stack = new Splstack ();
$this->generator = $generator; Public Function run () {while (1) {try {if (! $this->generator->vali
D ()) {if (! $this->stack->isempty ()) {try {
$this->return = $this->generator->getreturn ();
The catch (Exception $e) {$this->return = null;
$this->generator = $this->stack->pop (); /** * Assigns the return value in the child generator to the parent generator the current yield expression as the result; * and executes the next parent yield expression
; * If the next parent yield expression is not executed here, generator will always be in this yield, the following will die loop; The following sub generator performs the Send method in logical Analysis $this->generator->send ($this->return);
Continue
} return;
/** * Sub Generator perform logical analysis: * 1. Gets the result value of the current yield expression;
* 2. If result is a generator generator; * 3. Then the currently executing generator into the stack (the currently executing generator is the generator attribute in the Taskstack Class);
* 4. Execution generator, child generator execution completed, get return value; * # # This moment of the Send method function, ingenious design;
* # 5.send method takes the return value of a generator as the result value of the yield expression of the parent generator interrupt; * # 6. Continue to execute the parent generator; * # # if not 5 and 6, then return to 1 after the 4 execution, death cycle;/$this->return = $this->generator->cur
rent ();
if ($this->return instanceof Generator) {$this->stack->push ($this->generator); $this->generator = $this->return;
Continue /** * Asynchronous Execution Logical Analysis: * 1. Gets the value of the current yield expression;
2. If result is a special asynchronous class (The custom class or interface is used to handle asynchronous operations);
* 3. Send the closure function closure to the asynchronous callback function, that is, when the asynchronous operation completes and the callback function executes, the closure of the send is performed; * Closure operation:
* 1. Sends the result of the asynchronous execution to the yield expression currently executing as the result value through the Send method; * 2. Continue to execute the Taskstack run () and continue executing the generator; * 4. Direct end of the stack run () method; * # # Combine to say that if an expression is encountered with the value of an asynchronous class, *
# # so that the execution of the current taskstack is ended directly until the asynchronous callback function is executed; * # Note that the generator stops executing, it is not blocked for the process, the process can perform other actions; */if ($this->return instanceof asyncsss) {$this->return->delivery ( function () {echo ' time '. Time ().
Php_eol;
$this->generator->send ("async return"); $this->run ();
});
Return
$this->generator->send ($this->return);
catch (Exception $e) {throw $e; The Public Function end () {return $this->stack->isempty () &&! $this->gene
Rator->valid ();
} class Asyncsss {public $second;
Public function after ($second) {$this->second = $second;
return $this;
The Public function delivery (Closure $callback) {swoole_timer_after ($this->second, $callback); } function Task1 () {echo ' Task1 before '.
Php_eol; echo "Time". Time ().
Php_eol;
$async = yield (new asyncsss)->after (3000); echo "Task1 get async return value: $async".
Php_eol;
$generator = yield task1_1 (); echo "Task1 get Task2 return value: $generator".
Php_eol; echo "Task1 after".
Php_eol; }
function Task1_1 () {echo "task1_1 before".
Php_eol;
$value = yield task1_1_1 (); echo "Task1_1 get task1_1_1 return value: $value".
Php_eol; echo "Task1_1 after".
Php_eol;
Return to ' task1_1 return ';
function Task1_1_1 () {return ' task1_1_1 return ';}
$a = new Taskstack (Task1 ());
$a->run (); Echo ' Task stack run '.
Php_eol; /** * Output: * task1 before * time 1511331788 * Task stack run after * time 1511331791 * Task1 get async return value: Async return * task1_1 before * task1_1 get task1_1_1 return value:task1_1_1 return * task1_1 after * Task1 get TAS K2 return value:task1_1 return * TASK1 after * *