Send your request Join Sii

In the first part of the series I introduced ideas of cooperative multitasking, generators and yield keyword. You were also able to learn a bit about generator return expressions and I showed how yield can be used to interrupt linear flow of execution.

Next example shows how another brand new feature can be used – generator delegation:

/**
* Generator
* @return string
*/
$generatorWithTwoWayCommunication = function()
{
$randomValue = mt_rand();
yield $randomValue;
$receivedFromOuterSpace = yield;
$returnValue = yield from subGenerator($receivedFromOuterSpace, $randomValue);
return $returnValue;
};
 
/**
* Subgenerator
* @return string
*/
function subGenerator($valueFromOuterSpace, $randomValue)
{
yield $valueFromOuterSpace * $valueFromOuterSpace;
yield $valueFromOuterSpace * $randomValue;
return 'Lis Witalis';
};
 
/**
* Main flow
*/
$generator = $generatorWithTwoWayCommunication();
$valueFromFirstIteration = $generator->current();
$generator->next();
$valueFromSecondIteration = $generator->send(666);
$generator->next();
$valueFromThirdIteration = $generator->current();
$generator->next();
$valueReturnedFromGenerator = $generator->getReturn();

The image below explains the execution flow of generator delegation example.

Coroutine example flow II
Coroutine example utilising generator return expression and generator delegation

As you can see it seems to be possible to develop asynchronous application in PHP. There is however quite an important PHP property that might be easily overseen when you start thinking about implementing Generator-base coroutines. The trap is hidden in Listing 2 in the first part and consists of a single line:

stream_set_blocking($socket, 0);

When you overcome unfriendliness of Generators and coroutines implementation and you start thinking about implementing them in your application then you will suddenly realise that the biggest obstacle to write asynchronous code in PHP lies elsewhere: PHP is synchronous by its very nature and virtually all the streams that are opened with defaults settings (including sockets) are blocking. It means that your options to make use of coroutines efficiently are limited to some solutions that are available in the wild and very few that are baked into PHP.

The most obvious example of asynchronous PHP framework is probably React. It supports basically all the stream operations but is still limited to user land code. Guzzle 6 is quite a decent option too but same limitations apply and you are required to implement quite a lot of logic on our own. Various C extensions that offer joy of asynchronism are pretty similar – Swoole will not miraculously make PHP stream asynchronous.

If you try to send asynchronous requests to the database (and you are not too keen to implement your own client library in pure PHP) then you are limited to mysqli with mysqlnd (for MySQL) and pg_send_query function (for Postgresql). None of other database drivers or extensions (including PDO) supports asynchronous operations. When you realise that one of the very first asynchronous features implemented in Hack was MySQL support then you may come to a conclusion that writing this very type of applications in PHP is not the best idea.

I wholeheartedly agree with the finding. Developing asynchronous applications in PHP does not seem to be a feasible option. There are lots of other languages out there that support asynchronism to great extent. If you want to stick to PHP ecosystem then Hack might be a decent option. You should keep in mind that this is still a project that mainly Facebook developers contribute to and it’s hard to predict its future (Wikimedia Foundation move to HHVM is an encouraging decision however). Hack supports asynchronous memcached and MySQL communication as well as various I/O operations.

If you prefered to try enterprise solution then .Net framework is one of the options available. You will get asynchronous HTTP requests, and file operations, and sound and video capture, and image file manipulation out of the box. Using AsyncPattern should allow you to achieve much more and, as far as I understand from what documentation states, one should be able to desynchronise majority of the code (as long as sockets do not block).

You will find even more opportunities in the world of JVM. Java offers Future interface that can represent result of an asynchronous call. If you wish to develop complex applications you may want to take a look at Akka framework (that implements its own version of futures) which is focused on concurrent applications and is non-blocking by design.

There is yet another option out there that seems to be the most feasible one when it comes to asynchrony. Asynchronous operations have been core to many web applications for a while. They were available on the client side first but since 2009 Node.js has been publicly available. V8 performance combined with Javascript non-blocking character are, in my opinion, the best solution money can buy for asynchronous web development as of now.

When you start thinking about adding asynchronous features to PHP application that you develop you should keep in mind that it will increase complexity of your platform. Even if you follow my advice and give up PHP for some functionalities then you will have to introduce microservice (or microservices) to be able to use additional language on a back end. If you are really sure that you want your product to utilise asynchrony then you should make this decision at an early stage as chosing wrong platform might affect your project’s future. PHP is great language but Popov’s words about generators and coroutines should be kept in mind:

There is a thin line between awesome code and a total mess and I think coroutines sit exactly on that line.

Sources and further reading:

4/5 ( vote: 1)
Rating:
4/5 ( vote: 1)
Author
Avatar
Maciej Iwanowski

Developer, fan of TDD, train-spotter, one-time poet. Co-founder of 3cloud.io and co-organizer of Tricity AWS User Group Poland. Interested in concurrency and distributed system. Devotee of third wave of coffee.

Leave a comment

Your email address will not be published. Required fields are marked *

You might also like

More articles

Don't miss out

Subscribe to our blog and receive information about the latest posts.

Get an offer

If you have any questions or would like to learn more about our offer, feel free to contact us.

Send your request Send your request

Natalia Competency Center Director

Get an offer

Join Sii

Find the job that's right for you. Check out open positions and apply.

Apply Apply

Paweł Process Owner

Join Sii

SUBMIT

Ta treść jest dostępna tylko w jednej wersji językowej.
Nastąpi przekierowanie do strony głównej.

Czy chcesz opuścić tę stronę?