search
HomeBackend DevelopmentPHP TutorialDetailed introduction to coroutines in php (code)

This article first introduces the concept of generator, focusing on the usage of yield and the interface of generator. The coroutine part briefly explains the principles of coroutines and matters that should be paid attention to in PHP coroutine programming.

PHP has introduced generator (Generator) since 5.5, based on which coroutine programming can be realized. This article starts with a review of generators and then transitions to coroutine programming.

yield and generator

Generator

Generator is a data type that implements the iterator interface. The generator instance cannot be obtained through new, and there is no static method to obtain the generator instance. The only way to get a generator instance is to call the generator function (a function containing the yield keyword). Calling the generator function directly returns a generator object, and the code within the function starts executing when the generator is running.

First go to the code to intuitively experience yield and generators:

# generator1.php
function foo() {
    exit('exit script when generator runs.');
    yield;
}

$gen = foo();
var_dump($gen);
$gen->current();

echo 'unreachable code!';

# 执行结果
object(Generator)#1 (0) {
}
exit script when generator runs.

fooThe function contains the yield keyword and transforms into a generator function. Calling foo does not execute any code in the function body, but instead returns a generator instance. After the generator runs, the code within the foo function is executed and the script ends.

As the name suggests, generators can be used to generate data. It’s just that the way it generates data is different from other functions: the generator returns data through yield instead of return; After yield returns data, the generator function does not It will be destroyed, it just pauses the operation, and it can be resumed from the pause in the future; the generator will return (only) one data if it is run once, and multiple data will be returned if it is run multiple times; if the generator is not called to obtain data, the code in the generator will lie there. The so-called "moving every time" refers to the way the generator generates data.

The generator implements the iterator interface. To obtain the generator data, you can use foreach loop or manual current/next/valid. The following code demonstrates data generation and traversal:

# generator2.php
function foo() {
  # 返回键值对数据
  yield "key1" => "value1";
  $count = 0;
  while ($count valid()) {
  fwrite(STDOUT, "key:{$gen->key()}, value:{$gen->current()}\n");
  $gen->next();
}

# foreach 遍历数据
fwrite(STDOUT, "\ndata from foreach\n");
foreach (foo() as $key => $value) {
    fwrite(STDOUT, "key:$key, value:$value\n");
}

yield

yieldThe keyword is the core of the generator, which allows ordinary functions to differentiate (evolve) into generator functions. yield means "giving up". When the program executes to the yield statement, it will pause execution, yield the CPU and return control to the caller. The next execution will continue from the interruption point. implement. When control returns to the caller, the yield statement can return the value to the caller. generator2.phpThe script demonstrates the three forms of yield return values:

  1. yield $key => $value: Returns the key and value of the data;

  2. yield $value: Returns data, key is allocated by the system;

  3. yield: Returns null value, key is allocated by the system;

yieldAllows the function to pause, continue execution at any time, and return data to the caller. If external data is needed to continue execution, this work is provided by the send function of the generator: the variable that appears on the left side of yield will receive the variable from send value. Let’s look at a common send function usage example:

function logger(string $filename) {
  $fd = fopen($filename, 'w+');
  while($msg = yield) {
    fwrite($fd, date('Y-m-d H:i:s') . ':' . $msg . PHP_EOL);
  }
  fclose($fd);
}

$logger = logger('log.txt');
$logger->send('program starts!');
// do some thing
$logger->send('program ends!');

send The ability to have two-way data communication between generators and the outside: yieldReturn data; send Provide support data for continued operation. Since send allows the generator to continue executing, this behavior is similar to the next interface of the iterator, where next is equivalent to send(null).

Others

  1. $string = yield $data; expression is not legal before PHP7 and requires parentheses: $string = (yield $data);

  2. ##PHP5 generator function cannot

    return value, after PHP7 it can return value and pass the of the generator getReturnGet the returned value.

  3. PHP7 adds the

    yield from syntax to implement generator delegation.

  4. The generator is a one-way iterator, and

    rewind cannot be called after it is started.

Summary

Compared with other iterators, generators have the characteristics of low performance overhead and easy coding. Its role is mainly reflected in three aspects:

  1. Data generation (producer), returning data through yield;

  2. Data consumption (consumer) ), consume the data from send;

  3. implements the coroutine.

Regarding generators and basic usage in PHP, it is recommended to read the blog post of

2gua: PHP Generator is lively, interesting and easy to understand.

Coroutine programming

Coroutine (coroutine) is a subroutine that can be interrupted and resumed at any time. The

yield keyword allows the function to have this ability, so it can be used For coroutine programming.

Processes, threads and coroutines

Threads belong to processes, and a process can have multiple threads. A process is the smallest unit for computer allocation of resources, and a thread is the smallest unit for computer scheduling and execution. Both processes and threads are scheduled by the operating system.

Coroutines can be regarded as "user-mode threads" and require user programs to implement scheduling. Threads and processes are scheduled by the operating system to run alternately in a "preemptive" manner, and coroutines actively give up the CPU to run alternately in a "negotiative" manner. Coroutines are very lightweight, coroutine switching does not involve thread switching, and the execution efficiency is high. The greater the number, the better the advantages of coroutines can be reflected.

Generator and coroutine

The coroutine implemented by the generator is a stackless coroutine, that is, the generator function only has a function frame, which is attached to the caller's stack during runtime for execution. Unlike the powerful stackful coroutine, the generator cannot control the direction of the program after it is paused, and can only passively return control to the caller; the generator can only interrupt itself, not the entire coroutine. Of course, the advantage of the generator is that it is highly efficient (you only need to save the program counter when pausing) and is simple to implement.

Coroutine Programming

Speaking of coroutine programming in PHP, I believe most people have read this blog post reprinted (translated) by Brother Niao: Using coroutines to achieve multiple functions in PHP Task scheduling. The original author nikic is the core developer of PHP, the initiator and implementer of the generator function. If you want to learn more about generators and coroutine programming based on them, nikic's RFC on generators and the articles on Niaoge's website are must-reads.

Let’s first look at the working method of coroutines based on generators: coroutines work collaboratively, that is, coroutines actively give up the CPU to achieve alternate running of multiple tasks (that is, concurrent multitasking, but not parallel); A generator can be regarded as a coroutine. When the yield statement is executed, the CPU control is returned to the caller, and the caller continues to execute other coroutines or other codes.

Let’s look at the difficulty in understanding Brother Bird’s blog. Coroutines are very lightweight, and thousands of coroutines (generators) can exist in a system at the same time. The operating system does not schedule coroutines, and the work of arranging coroutine execution falls on developers. Some people don’t understand the coroutine part of Brother Niao’s article because it says there is little coroutine programming (writing coroutines mainly means writing generator functions), but they spend a lot of time implementing a coroutine scheduler (scheduler or kernel). : Simulates the operating system and performs fair scheduling on all coroutines. The general thinking of PHP development is: I wrote these codes, and the PHP engine will call my codes to get the expected results. Coroutine programming requires not only writing code to do the work, but also writing code to instruct these codes when to work. If you don’t have a good grasp of the author’s thinking, it will naturally be more difficult to understand. It needs to be scheduled by itself, which is a disadvantage of the generator coroutine compared to the native coroutine (async/await form).

Now that we know what coroutine is, what can it be used for? The coroutine gives up the CPU on its own to cooperate and efficiently utilize the CPU. Of course, the time to give up should be when the program is blocked. Where will the program block? User-mode code rarely blocks, and blocking is mainly caused by system calls. The majority of system calls are IO, so the main application scenario of coroutines is network programming. In order to make the program high performance and high concurrency, the program should execute asynchronously and not block. Since asynchronous execution requires notifications and callbacks, writing callback functions cannot avoid the problem of "callback hell": code readability is poor, and the program execution process is scattered among layers of callback functions. There are two main ways to solve callback hell: Promise and coroutines. Coroutines can write code in a synchronous manner and are recommended in high-performance network programming (IO-intensive).

Let’s look back at coroutine programming in PHP. In PHP, coroutine programming is implemented based on generators. It is recommended to use coroutine frameworks such as RecoilPHP and Amp. These frameworks have already written schedulers. If you develop a generator function directly on it, the kernel will automatically schedule execution (if you want a function to be scheduled for execution in a coroutine mode, just add yield to the function body. ). If you don’t want to use the yield method for coroutine programming, we recommend swoole or its derivative framework, which can achieve a coroutine programming experience similar to golang and enjoy the development efficiency of PHP.

If you want to use the original PHP coroutine programming, a scheduler similar to the one in Niao Ge's blog is essential. The scheduler schedules the execution of the coroutine. After the coroutine is interrupted, control returns to the scheduler. Therefore, the scheduler should always be in the main (event) loop, that is, when the CPU is not executing the coroutine, it should be executing the scheduler code. When running without a coroutine, the scheduler should block itself to avoid consuming the CPU (Niao Ge's blog uses the built-in select system call), wait for the event to arrive, and then execute the corresponding coroutine. During the running of the program, except for scheduler blocking, the coroutine should not call blocking APIs during running.

Summary

In coroutine programming, the main function of yield is to transfer control without worrying about its return value (basically yieldThe returned value will be send directly during the next execution). The focus should be on the timing of the transfer of control and how the coroutine operates.

In addition, it needs to be explained that coroutines have little to do with asynchrony, and it also depends on the running environment support. In the conventional PHP operating environment, even if promise/coroutine is used, it is still blocked synchronously. No matter how awesome the coroutine framework is, sleep is no longer easy to use. As an analogy, even if JavaScript does not use promise/async technologies, it is asynchronous and non-blocking.

Through generators and Promise, coroutine programming similar to await can be implemented. There is a lot of relevant code on Github and will not be given in this article.

Related recommendations:

$_SERVER in PHP Detailed introduction

Detailed introduction to output_buffering in PHP, outputbuffering_PHP tutorial

The above is the detailed content of Detailed introduction to coroutines in php (code). For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
How does PHP type hinting work, including scalar types, return types, union types, and nullable types?How does PHP type hinting work, including scalar types, return types, union types, and nullable types?Apr 17, 2025 am 12:25 AM

PHP type prompts to improve code quality and readability. 1) Scalar type tips: Since PHP7.0, basic data types are allowed to be specified in function parameters, such as int, float, etc. 2) Return type prompt: Ensure the consistency of the function return value type. 3) Union type prompt: Since PHP8.0, multiple types are allowed to be specified in function parameters or return values. 4) Nullable type prompt: Allows to include null values ​​and handle functions that may return null values.

How does PHP handle object cloning (clone keyword) and the __clone magic method?How does PHP handle object cloning (clone keyword) and the __clone magic method?Apr 17, 2025 am 12:24 AM

In PHP, use the clone keyword to create a copy of the object and customize the cloning behavior through the \_\_clone magic method. 1. Use the clone keyword to make a shallow copy, cloning the object's properties but not the object's properties. 2. The \_\_clone method can deeply copy nested objects to avoid shallow copying problems. 3. Pay attention to avoid circular references and performance problems in cloning, and optimize cloning operations to improve efficiency.

PHP vs. Python: Use Cases and ApplicationsPHP vs. Python: Use Cases and ApplicationsApr 17, 2025 am 12:23 AM

PHP is suitable for web development and content management systems, and Python is suitable for data science, machine learning and automation scripts. 1.PHP performs well in building fast and scalable websites and applications and is commonly used in CMS such as WordPress. 2. Python has performed outstandingly in the fields of data science and machine learning, with rich libraries such as NumPy and TensorFlow.

Describe different HTTP caching headers (e.g., Cache-Control, ETag, Last-Modified).Describe different HTTP caching headers (e.g., Cache-Control, ETag, Last-Modified).Apr 17, 2025 am 12:22 AM

Key players in HTTP cache headers include Cache-Control, ETag, and Last-Modified. 1.Cache-Control is used to control caching policies. Example: Cache-Control:max-age=3600,public. 2. ETag verifies resource changes through unique identifiers, example: ETag: "686897696a7c876b7e". 3.Last-Modified indicates the resource's last modification time, example: Last-Modified:Wed,21Oct201507:28:00GMT.

Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1?Explain secure password hashing in PHP (e.g., password_hash, password_verify). Why not use MD5 or SHA1?Apr 17, 2025 am 12:06 AM

In PHP, password_hash and password_verify functions should be used to implement secure password hashing, and MD5 or SHA1 should not be used. 1) password_hash generates a hash containing salt values ​​to enhance security. 2) Password_verify verify password and ensure security by comparing hash values. 3) MD5 and SHA1 are vulnerable and lack salt values, and are not suitable for modern password security.

PHP: An Introduction to the Server-Side Scripting LanguagePHP: An Introduction to the Server-Side Scripting LanguageApr 16, 2025 am 12:18 AM

PHP is a server-side scripting language used for dynamic web development and server-side applications. 1.PHP is an interpreted language that does not require compilation and is suitable for rapid development. 2. PHP code is embedded in HTML, making it easy to develop web pages. 3. PHP processes server-side logic, generates HTML output, and supports user interaction and data processing. 4. PHP can interact with the database, process form submission, and execute server-side tasks.

PHP and the Web: Exploring its Long-Term ImpactPHP and the Web: Exploring its Long-Term ImpactApr 16, 2025 am 12:17 AM

PHP has shaped the network over the past few decades and will continue to play an important role in web development. 1) PHP originated in 1994 and has become the first choice for developers due to its ease of use and seamless integration with MySQL. 2) Its core functions include generating dynamic content and integrating with the database, allowing the website to be updated in real time and displayed in personalized manner. 3) The wide application and ecosystem of PHP have driven its long-term impact, but it also faces version updates and security challenges. 4) Performance improvements in recent years, such as the release of PHP7, enable it to compete with modern languages. 5) In the future, PHP needs to deal with new challenges such as containerization and microservices, but its flexibility and active community make it adaptable.

Why Use PHP? Advantages and Benefits ExplainedWhy Use PHP? Advantages and Benefits ExplainedApr 16, 2025 am 12:16 AM

The core benefits of PHP include ease of learning, strong web development support, rich libraries and frameworks, high performance and scalability, cross-platform compatibility, and cost-effectiveness. 1) Easy to learn and use, suitable for beginners; 2) Good integration with web servers and supports multiple databases; 3) Have powerful frameworks such as Laravel; 4) High performance can be achieved through optimization; 5) Support multiple operating systems; 6) Open source to reduce development costs.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
1 months agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat Commands and How to Use Them
1 months agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool