PHP implementation coroutine

Source: Internet
Author: User
PHP implements coroutine in server programming. in order to implement asynchronization, callback functions are often required. for example, the following code

function send($value) {    $data = process($value);    onReceive($data);}function onReceive($recv_value) {    var_dump($recv_value);}function process($value) {    return $value+1;}$send_value = 1;send($send_value);

The implementation is very simple. In fact, send_value is sent to the remote end. after the remote server adds one to the value, it is sent back. Therefore, in onReceive, we can obtain the return value recv_value of the remote server.

However, such code looks fragmented, especially when the remote process is called again in the process, it becomes more difficult to develop and maintain. The coroutine is designed to solve this problem and make the asynchronous code look synchronous.

The following is an example of using php yield to schedule code (if you want to understand this code, you need to first understand the new features of php 5.5 generator and yield)

The framework code is as follows:

Class CCoroutine {/***** @ var Generator */public $ coroutine;/***** @ var miexed null or CCoroutine */public $ father; public function _ construct ($ coroutine, $ father = null) {$ this-> coroutine = $ coroutine; $ this-> father = $ father ;}} class AsyncTask {public $ data; public function _ construct ($ data) {$ this-> data = $ data ;}abstract class coroutineschedted {protected $ coroutine = NULL; release Ct function send_and_receive ($ value); public function run ($ data) {$ co = $ this-> send_and_receive ($ data); $ ccoroutine = new CCoroutine ($ co ); $ this-> schedule ($ ccoroutine);} protected function schedule ($ ccoroutine) {$ task = $ ccoroutine-> coroutine-> current (); // if the current value is null, the $ ccoroutine should have ended if (is_null ($ task) {if (is_null ($ ccoroutine-> father )) {// The scheduling has been completed. Generally, the onRecieve method runs to the last step. return;} else {// Note: If you run to this branch, it indicates that the sub-generator has not passed data to the parent generator. // The sub-generator may change the variable value of the parent generator through reference transmission. // at this time, you only need to schedule the parent generator. $ ccoroutine -> father-> coroutine-> next (); $ father = $ ccoroutine-> father; $ this-> schedule ($ father); unset ($ ccoroutine) ;}} else {if (is_object ($ task) & $ task instanceof AsyncTask) {// when the task is an asynchronous data request, start to process the socket and kill the process here $ this-> dealTask ($ task, $ ccoroutine);} elseif (is_object ($ task) & $ task instanceof \ Generator) {// When a task is a generator, it indicates that the current generator has a subgenerator call $ newcc = new CCoroutine ($ task, $ ccoroutine ); $ this-> schedule ($ newcc);} elseif ($ ccoroutine-> father! = Null) {// note that if you run to this branch, yield $ str is called in the sub-generator; this writing method // we stipulate that this writing method is to transmit data to the parent generator, therefore, the current generator will terminate the call and then dispatch the parent generator $ ccoroutine-> father-> coroutine-> send ($ task); $ father = $ ccoroutine-> father; $ this-> schedule ($ father); unset ($ ccoroutine) ;}} protected function dealTask ($ task, $ ccoroutine) {$ this-> coroutine = $ ccoroutine; $ this-> send ($ task-> data);} public function send ($ value) {$ data = $ this-> process ($ value ); $ this-> onReceive ($ data);} public function process ($ value) {return $ value + 1;} protected function onReceive ($ data) {$ this-> coroutine-> send ($ data); $ this-> schedule ($ this-> coroutine );}}

The framework encapsulates all the functions such as send and onReceive, so that the caller's code looks like Synchronous Code.

The caller code is as follows:

// 1. you need to implement the send_and_receive function of CoroutineScheduler to obtain the returned class Solution extends CoroutineScheduler {public function send_and_receive ($ data) {$ result = (yield new AsyncTask ($ data); var_dump ($ result) ;}// 2. call the framework code at the outermost layer and provide the input parameter $ data $ s = new Solution (); $ data = 1; $ s-> run ($ data );

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.