Chức năng trì hoãn php

Tuy nhiên, ví dụ. Nếu bạn muốn tìm tải dữ liệu từ nhiều URL và tóm tắt kết quả, bạn muốn thực hiện các yêu cầu HTTP cùng thời gian một lúc. Có một thư viện tên là Guzzle cho mục đích này, cho phép bạn thực hiện các yêu cầu cùng một lúc. Nhưng điều gì sẽ xảy ra nếu bạn muốn truy cập HTTP và truy cập DB cùng một lúc?

Vì vậy, một RFC đã được tạo ra cho phép bạn viết xử lý không đồng bộ có mục đích chung trong PHP. URL tham khảo. https. //wiki. php. mạng/rfc/sợi

Đánh lừa URL. https. //github. com/guzzle/guzzle

PHP RFC. sợi

Giới thiệu

Từ trước đến nay, hầu như người ta chỉ viết PHP dưới dạng mã đồng bộ. Chỉ có mã chạy đồng bộ tồn tại, và chúng được gọi là một cách đồng bộ. Các hàm đồng bộ tiếp tục xử lý cho đến khi hàm trả về một kết quả

Hôm nay, có một số dự án cho phép bạn viết mã PHP không đồng bộ. Các hàm không đồng bộ thực thi mã sau khi thu được kết quả, giả sử hạn chế như bằng cách nhận lệnh Gọi lại hoặc trả về PlaceHolder có giá trị được cố định sau đó, như Lời hứa. Điều này cho phép bạn tiếp tục xử lý mà không cần đợi kết quả cuối cùng. Ví dụ. amphp, ReactPHP và Guzzle

Những công thức mà RFC đang cố gắng giải quyết rất khó giải thích, nhưng tôi sẽ cố gắng giải thích về vấn đề này

Để tóm tắt các vấn đề được mô tả trong bài viết của URL wiki ở trên. -Các hàm không đồng bộ "trót lỡ" thay đổi cơ chế gọi các hàm. -Các hàm không đồng bộ không thể gọi các hàm không đồng bộ. Bạn có thể gọi một chức năng đồng bộ hóa. - Để gọi một hàm không đồng bộ, toàn bộ ngăn xếp cuộc gọi phải là không đồng bộ

Đối với những người đã quen với Promise, thường phải đợi cho quá trình xử lý không đồng bộ, có thể đã nghĩ đến điều này. "Nếu bạn cố gắng trả lại một Promise ở bất kỳ đâu trong Call Stack, toàn bộ Call Stack sẽ phải trả lại một Promise vì bạn không biết khi nào nó sẽ được giải quyết. "

RFC ra đời Mục đích lý giải các số không đồng bộ và các hàm không đồng bộ mà không có sự phân biệt bằng cách đưa vào quá trình xử lý không đồng bộ có thể bị gián đoạn xử lý mà không ảnh hưởng đến toàn bộ cuộc gọi . Điều này đạt được như sau

- Hỗ trợ Fiber trong PHP. -Thêm lớp Fiber và lớp phản xạ tương ứng ReflectionFiber. -Thêm các lớp FiberError và FiberExit cho các lỗi

Fiber cho phép bạn khai thác IO non proxy trên các giao diện hiện có như PSR-7 và Doctine ORM. Điều này là không sử dụng các Placeholder như Promise

Về Fiber Fiber cho phép bạn tạo các chức năng ngăn xếp đầy đủ có khả năng phân tách ra. This is also call is coroutine or green thread

Fiber could Stop toàn bộ ngăn xếp thực thi, vì vậy người gọi hàm không cần thay đổi lệnh gọi

You can could use Fiber. pause[] to pause theo ý muốn. Call to Fiber. Suspements [] may be lồng sâu trong hàm or it could not at any where

Không giống như Generator không có Stack, Fiber giữ ngăn xếp cuộc gọi của riêng nó, vì vậy nó có thể tạm dừng ngay cả khi trong phần cuộc gọi có chứa các hàm phức tạp xen kẽ. Not same as Generators, must return a Generator Instance, functions used Fiber is not need to change the return type

Fiber could be pause pause with any command call function any, real as array_map, Iterator foreach or a call from side in a PHP server. Để tiếp tục một Fiber bị tạm dừng, hãy tiếp tục với Fiber->resume [] hoặc ném một ngoại lệ với Fiber-> throw[]. , Giá trị được trả lại bằng Fiber. susu[] hoặc một ngoại lệ bị ném ra

Fiber is default by PHP core、 signature as after

final class Fiber
{
    /**
     * @param callable $callback Hàm callback
     */
    public function __construct[callable $callback] {}

    /**
     * Bắt đầu chạy
     *
     * @param mixed ...$args Param được đưa cho hàm callback
     *
     * @return mixed Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu đã được chạy
     * @throw Throwable Others
     */
    public function start[mixed ...$args]: mixed {}

    /**
     * Mở lại fiber đang bị gián đoạn.
     *
     * @param mixed $value
     *
     * @return mixed Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu chưa được chạy, hay hiện tại đang tạm ngừng, Hoặc đã kết thúc 
     * @throw Throwable Others
     */
    public function resume[mixed $value = null]: mixed {}

    /**
     * Ví dụ 
     *
     * @param Throwable $exception
     *
     * @return mixed 一Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu chưa được chạy, hay hiện tại đang tạm ngừng, Hoặc đã kết thúc 
     * @throw Throwable Others
     */
    public function throw[Throwable $exception]: mixed {}

    /**
     * @return bool Đã bắt đầu chạy thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu ngừng tạm thời thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy  thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu việc chạy đã kết thúc thì là true
     */
    public function isTerminated[]: bool {}

    /**
     * @return mixed Trả giá trị hoàn lại của hàm callback 
     *
     * @throws FiberError Chưa xong
     */
    public function getReturn[]: mixed {}

    /**
     * @return self|null Trả về Fiber Instance đang chạy trong hiện tại
     */
    public static function this[]: ?self {}

    /**
     * Tạm ngừng việc chạy. Không gọi ra từ main thread.
     *
     *  Giả trị trả về từ throw[] hay @param mixed resume[]
     *
     * Giá trị đưa cho @return mixed resume[]
     *
     * @throws FiberError Gọi từ main thread chẳng hạn 
     * @throws Throwable Others
     */
    public static function suspend[mixed $value = null]: mixed {}
}

Tạo một đối tượng Fiber bằng cách truyền một hàm gọi lại tùy chọn làm Fiber mới [$ callback can call back]. Recall function is not most device must call Fiber. Susan []. Nó có thể nằm sâu trong ngăn xếp lồng nhau hoặc có thể không bao giờ được gọi

đối tượng Fiber được tạo được bắt đầu bằng cách truyền Fiber-> bắt đầu [hỗn hợp. $ args] và các đối số

Chất xơ. pause[] tạm dừng việc thực thi Fiber current and return too trình cho cuộc gọi của Fiber->start[], Fiber->resume[], Fiber->throw[]. Bạn có thể coi nó như một cái gì đó tương tự như năng suất trong Generator

Finer has beentreo can be connect back by two way after. --Khởi động lại bằng cách chuyển một giá trị cho Fiber->resume[]. --Exception by way transfer a value for Fiber-> throw[]

Từ Fiber đã xử lý, bạn có thể nhận giá trị trả về của hàm gọi lại với Fiber-> getReturn[]. Lỗi FiberError được đưa ra khi quá trình thực thi không được hoàn thành hoặc một số trường hợp ngoại lệ xảy ra

Chất xơ. this [] return to the Fiber is being running. Điều này cho phép bạn đưa Sợi tham chiếu đến một vị trí khác, ví dụ như vòng lặp cuộc gọi lại sự kiện hoặc một mảng các sợi có thể bị treo

Reflection Fiber Reflection Fiber là phương thức kiểm tra Fiber đang chạy. Bạn có thể tạo Reflection Fiber từ bất kỳ đối tượng Fiber nào, cho dù nó được thực hiện trước hay hoàn tất. ReflectionFiber rất giống với ReflectionGenerator


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}

Fiber is not complete to Fiber, same as a bình thường đối tượng, bị hủy khi không còn tham chiếu đến đối tượng

Khi đó, Fiber chưa được thực thi sẽ bị hủy giống như Generator chưa được thực thi. Unable to call back Fiber was abort by Fiber. Susan []

** Ngăn xếp sợi **

Mỗi luồng được gán một ngăn xếp C riêng biệt và ngăn xếp VM trên heap. Ngăn xếp C được bổ sung bằng mmap khi có sẵn. Đó là, bộ nhớ vật lý được sử dụng theo yêu cầu trên hầu hết các nền tảng. Mỗi ngăn xếp Sợi được cấp phát tối đa 8M theo mặc định và có thể được thay đổi với thiết lập ini sợi. kích thước ngăn xếp. Lưu ý rằng bộ nhớ này được cấp cho stack C và không liên quan gì đến bộ nhớ được PHP sử dụng

ngăn xếp VM bộ phận bổ sung bộ nhớ và CPU theo cách giống như Trình tạo. Do ngăn xếp VM không thể thay đổi động nên chỉ 4K được sử dụng ở trạng thái ban đầu

The change to reverse do not compatible Các lớp Fiber / FiberError / FiberExit / ReflectionFiber được thêm vào không gian tên chung. There are no instead of change any other instead

Phạm vi tương lai

Việc phát triển hiện tại không cung cấp API Fiber nội bộ cho các phần mở rộng PHP. RFC this file trung vào API Fiber Userspace. Các nhà phát triển dự kiến ​​bổ sung API Fiber nội bộ với sự cộng tác của các mô-đun nhà phát triển tiện ích mở rộng khác. Họ sẽ nhận được phản hồi từ các nhà phát triển của phần mở rộng PHP như Swoole để cho phép phần mở rộng kiểm soát Fiber

Các mô-đun mở rộng có thể khai triển giống như Fiber của riêng họ, nhưng nếu một API nội bộ được cung cấp, họ sẽ có thể sử dụng khai thác Fiber của PHP Core

[Các] phiên bản PHP được đề xuất PHP 8. 1

Các ví dụ Ví dụ đơn giản Sau đây là một ví dụ đơn giản về Sợi được dừng bởi chuỗi ký tự là sợi. Chuỗi này được trả về từ $fibre->start[]. Sau đó, giá trị được truyền để tiếp tục được gửi đến Fiber. tạm ngừng []


$fiber = new Fiber[function []: void {
    $value = Fiber::suspend['fiber'];
    echo "Đã resume。$value: ", $value, "\n";
}];

$value = $fiber->start[];

echo "Đã tạm dừng。$value: ", $value, "\n";

$fiber->resume['test'];

// Kết quả chạy
Đã tạm dừng。$value: fiber
Đã resume。$value: test

vòng lặp sự kiện

Sau đây là một ví dụ về vòng lặp sự kiện rất đơn giản. Thăm dò soclet để nhận dữ liệu, rồi gọi lại khi có thể. vòng lặp sự kiện này chỉ cho phép khởi động lại Fiber khi có dữ liệu trên Socket, tránh bị chặn đọc

class EventLoop
{
    private string $nextId = 'a';
    private array $deferCallbacks = [];
    private array $read = [];
    private array $streamCallbacks = [];

    public function run[]: void
    {
        while [!empty[$this->deferCallbacks] || !empty[$this->read]] {
            $defers = $this->deferCallbacks;
            $this->deferCallbacks = [];
            foreach [$defers as $id => $defer] {
                $defer[];
            }

            $this->select[$this->read];
        }
    }

    private function select[array $read]: void
    {
        $timeout = empty[$this->deferCallbacks] ? null : 0;
        if [!stream_select[$read, $write, $except, $timeout, $timeout]] {
            return;
        }

        foreach [$read as $id => $resource] {
            $callback = $this->streamCallbacks[$id];
            unset[$this->read[$id], $this->streamCallbacks[$id]];
            $callback[$resource];
        }
    }

    public function defer[callable $callback]: void
    {
        $id = $this->nextId++;
        $this->deferCallbacks[$id] = $callback;
    }

    public function read[$resource, callable $callback]: void
    {
        $id = $this->nextId++;
        $this->read[$id] = $resource;
        $this->streamCallbacks[$id] = $callback;
    }
}

[$read, $write] = stream_socket_pair[
    stripos[PHP_OS, 'win'] === 0 ? STREAM_PF_INET : STREAM_PF_UNIX,
    STREAM_SOCK_STREAM,
    STREAM_IPPROTO_IP
];

// Đưa stream vào chế độ non proxy 
stream_set_blocking[$read, false];
stream_set_blocking[$write, false];

$loop = new EventLoop;

// Khi có thể đọc stream, lại khởi động việc đọc data bằng 1 cái Fiber khác nữa 
$fiber = new Fiber[function [] use [$loop, $read]: void {
    echo "Waiting for data...\n";

    $fiber = Fiber::this[];
    $loop->read[$read, fn[] => $fiber->resume[]];
    Fiber::suspend[];

    $data = fread[$read, 8192];

    echo "Received data: ", $data, "\n";
}];

// Chạy Fiber。
$fiber->start[];

// Đọc data bằng call back 
$loop->defer[fn[] => fwrite[$write, "Hello, world!"]];

// Chạy event loop
$loop->run[];

Kết quả

Waiting for data...
Received data: Hello, world!

Hình dưới đây để xem luồng thực thi giữa Main thread và Fiber Luồng thực thi đi qua lại mỗi khi bạn gọi Fiber. pause[] và Fiber->resume[]

Phan Duy Van @phanduyvan

Theo dõi

326 23 25

Đã đăng vào ngày 18 tháng 3 năm 2021 9. 12 SA 20 phút đọc

1. 8K

1

2

【PHP8. 1】 Để có thể viết xử lý bất đồng bộ 1 cách đơn giản trong PHP

  • Report
  • Add to series of me

Nguồn. https. //qiita. com/rana_kualu/items/6247441f6fdd63c10a06

PHP from long has been known to with the cách xử lý đồng bộ, tức là làm mọi thứ từ trên xuống dưới

Tuy nhiên, ví dụ. Nếu bạn muốn tìm tải dữ liệu từ nhiều URL và tóm tắt kết quả, bạn muốn thực hiện các yêu cầu HTTP cùng thời gian một lúc. Có một thư viện tên là Guzzle cho mục đích này, cho phép bạn thực hiện các yêu cầu cùng một lúc. Nhưng điều gì sẽ xảy ra nếu bạn muốn truy cập HTTP và truy cập DB cùng một lúc?

Vì vậy, một RFC đã được tạo ra cho phép bạn viết xử lý không đồng bộ có mục đích chung trong PHP. URL tham khảo. https. //wiki. php. mạng/rfc/sợi

Đánh lừa URL. https. //github. com/guzzle/guzzle

PHP RFC. sợi

Giới thiệu

Từ trước đến nay, hầu như người ta chỉ viết PHP dưới dạng mã đồng bộ. Chỉ có mã chạy đồng bộ tồn tại, và chúng được gọi là một cách đồng bộ. Các hàm đồng bộ tiếp tục xử lý cho đến khi hàm trả về một kết quả

Hôm nay, có một số dự án cho phép bạn viết mã PHP không đồng bộ. Các hàm không đồng bộ thực thi mã sau khi thu được kết quả, giả sử hạn chế như bằng cách nhận lệnh Gọi lại hoặc trả về PlaceHolder có giá trị được cố định sau đó, như Lời hứa. Điều này cho phép bạn tiếp tục xử lý mà không cần đợi kết quả cuối cùng. Ví dụ. amphp, ReactPHP và Guzzle

Những công thức mà RFC đang cố gắng giải quyết rất khó giải thích, nhưng tôi sẽ cố gắng giải thích về vấn đề này

Để tóm tắt các vấn đề được mô tả trong bài viết của URL wiki ở trên. -Các hàm không đồng bộ "trót lỡ" thay đổi cơ chế gọi các hàm. -Các hàm không đồng bộ không thể gọi các hàm không đồng bộ. Bạn có thể gọi một chức năng đồng bộ hóa. - Để gọi một hàm không đồng bộ, toàn bộ ngăn xếp cuộc gọi phải là không đồng bộ

Đối với những người đã quen với Promise, thường phải đợi cho quá trình xử lý không đồng bộ, có thể đã nghĩ đến điều này. "Nếu bạn cố gắng trả lại một Promise ở bất kỳ đâu trong Call Stack, toàn bộ Call Stack sẽ phải trả lại một Promise vì bạn không biết khi nào nó sẽ được giải quyết. "

RFC ra đời Mục đích lý giải các số không đồng bộ và các hàm không đồng bộ mà không có sự phân biệt bằng cách đưa vào quá trình xử lý không đồng bộ có thể bị gián đoạn xử lý mà không ảnh hưởng đến toàn bộ cuộc gọi . Điều này đạt được như sau

- Hỗ trợ Fiber trong PHP. -Thêm lớp Fiber và lớp phản xạ tương ứng ReflectionFiber. -Thêm các lớp FiberError và FiberExit cho các lỗi

Fiber cho phép bạn khai thác IO non proxy trên các giao diện hiện có như PSR-7 và Doctine ORM. Điều này là không sử dụng các Placeholder như Promise

Về Fiber Fiber cho phép bạn tạo các chức năng ngăn xếp đầy đủ có khả năng phân tách ra. This is also call is coroutine or green thread

Fiber could Stop toàn bộ ngăn xếp thực thi, vì vậy người gọi hàm không cần thay đổi lệnh gọi

You can could use Fiber. pause[] to pause theo ý muốn. Call to Fiber. Suspements [] may be lồng sâu trong hàm or it could not at any where

Không giống như Generator không có Stack, Fiber giữ ngăn xếp cuộc gọi của riêng nó, vì vậy nó có thể tạm dừng ngay cả khi trong phần cuộc gọi có chứa các hàm phức tạp xen kẽ. Not same as Generators, must return a Generator Instance, functions used Fiber is not need to change the return type

Fiber could be pause pause with any command call function any, real as array_map, Iterator foreach or a call from side in a PHP server. Để tiếp tục một Fiber bị tạm dừng, hãy tiếp tục với Fiber->resume [] hoặc ném một ngoại lệ với Fiber-> throw[]. , Giá trị được trả lại bằng Fiber. susu[] hoặc một ngoại lệ bị ném ra

Fiber is default by PHP core、 signature as after

final class Fiber
{
    /**
     * @param callable $callback Hàm callback
     */
    public function __construct[callable $callback] {}

    /**
     * Bắt đầu chạy
     *
     * @param mixed ...$args Param được đưa cho hàm callback
     *
     * @return mixed Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu đã được chạy
     * @throw Throwable Others
     */
    public function start[mixed ...$args]: mixed {}

    /**
     * Mở lại fiber đang bị gián đoạn.
     *
     * @param mixed $value
     *
     * @return mixed Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu chưa được chạy, hay hiện tại đang tạm ngừng, Hoặc đã kết thúc 
     * @throw Throwable Others
     */
    public function resume[mixed $value = null]: mixed {}

    /**
     * Ví dụ 
     *
     * @param Throwable $exception
     *
     * @return mixed 一Nếu ngừng tạm thời thì là suspension point。Nếu kết thúc thì là null
     *
     * @throw FiberError Nếu chưa được chạy, hay hiện tại đang tạm ngừng, Hoặc đã kết thúc 
     * @throw Throwable Others
     */
    public function throw[Throwable $exception]: mixed {}

    /**
     * @return bool Đã bắt đầu chạy thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu ngừng tạm thời thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy  thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu việc chạy đã kết thúc thì là true
     */
    public function isTerminated[]: bool {}

    /**
     * @return mixed Trả giá trị hoàn lại của hàm callback 
     *
     * @throws FiberError Chưa xong
     */
    public function getReturn[]: mixed {}

    /**
     * @return self|null Trả về Fiber Instance đang chạy trong hiện tại
     */
    public static function this[]: ?self {}

    /**
     * Tạm ngừng việc chạy. Không gọi ra từ main thread.
     *
     *  Giả trị trả về từ throw[] hay @param mixed resume[]
     *
     * Giá trị đưa cho @return mixed resume[]
     *
     * @throws FiberError Gọi từ main thread chẳng hạn 
     * @throws Throwable Others
     */
    public static function suspend[mixed $value = null]: mixed {}
}

Tạo một đối tượng Fiber bằng cách truyền một hàm gọi lại tùy chọn làm Fiber mới [$ callback can call back]. Recall function is not most device must call Fiber. Susan []. Nó có thể nằm sâu trong ngăn xếp lồng nhau hoặc có thể không bao giờ được gọi

đối tượng Fiber được tạo được bắt đầu bằng cách truyền Fiber-> bắt đầu [hỗn hợp. $ args] và các đối số

Chất xơ. pause[] tạm dừng việc thực thi Fiber current and return too trình cho cuộc gọi của Fiber->start[], Fiber->resume[], Fiber->throw[]. Bạn có thể coi nó như một cái gì đó tương tự như năng suất trong Generator

Finer has beentreo can be connect back by two way after. --Khởi động lại bằng cách chuyển một giá trị cho Fiber->resume[]. --Exception by way transfer a value for Fiber-> throw[]

Từ Fiber đã xử lý, bạn có thể nhận giá trị trả về của hàm gọi lại với Fiber-> getReturn[]. Lỗi FiberError được đưa ra khi quá trình thực thi không được hoàn thành hoặc một số trường hợp ngoại lệ xảy ra

Chất xơ. this [] return to the Fiber is being running. Điều này cho phép bạn đưa Sợi tham chiếu đến một vị trí khác, ví dụ như vòng lặp cuộc gọi lại sự kiện hoặc một mảng các sợi có thể bị treo

Reflection Fiber Reflection Fiber là phương thức kiểm tra Fiber đang chạy. Bạn có thể tạo Reflection Fiber từ bất kỳ đối tượng Fiber nào, cho dù nó được thực hiện trước hay hoàn tất. ReflectionFiber rất giống với ReflectionGenerator


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}

Fiber is not complete to Fiber, same as a bình thường đối tượng, bị hủy khi không còn tham chiếu đến đối tượng

Khi đó, Fiber chưa được thực thi sẽ bị hủy giống như Generator chưa được thực thi. Unable to call back Fiber was abort by Fiber. Susan []

** Ngăn xếp sợi **

Mỗi luồng được gán một ngăn xếp C riêng biệt và ngăn xếp VM trên heap. Ngăn xếp C được bổ sung bằng mmap khi có sẵn. Đó là, bộ nhớ vật lý được sử dụng theo yêu cầu trên hầu hết các nền tảng. Mỗi ngăn xếp Sợi được cấp phát tối đa 8M theo mặc định và có thể được thay đổi với thiết lập ini sợi. kích thước ngăn xếp. Lưu ý rằng bộ nhớ này được cấp cho stack C và không liên quan gì đến bộ nhớ được PHP sử dụng

ngăn xếp VM bộ phận bổ sung bộ nhớ và CPU theo cách giống như Trình tạo. Do ngăn xếp VM không thể thay đổi động nên chỉ 4K được sử dụng ở trạng thái ban đầu

The change to reverse do not compatible Các lớp Fiber / FiberError / FiberExit / ReflectionFiber được thêm vào không gian tên chung. There are no instead of change any other instead

Phạm vi tương lai

Việc phát triển hiện tại không cung cấp API Fiber nội bộ cho các phần mở rộng PHP. RFC this file trung vào API Fiber Userspace. Các nhà phát triển dự kiến ​​bổ sung API Fiber nội bộ với sự cộng tác của các mô-đun nhà phát triển tiện ích mở rộng khác. Họ sẽ nhận được phản hồi từ các nhà phát triển của phần mở rộng PHP như Swoole để cho phép phần mở rộng kiểm soát Fiber

Các mô-đun mở rộng có thể khai triển giống như Fiber của riêng họ, nhưng nếu một API nội bộ được cung cấp, họ sẽ có thể sử dụng khai thác Fiber của PHP Core

[Các] phiên bản PHP được đề xuất PHP 8. 1

Các ví dụ Ví dụ đơn giản Sau đây là một ví dụ đơn giản về Sợi được dừng bởi chuỗi ký tự là sợi. Chuỗi này được trả về từ $fibre->start[]. Sau đó, giá trị được truyền để tiếp tục được gửi đến Fiber. tạm ngừng []


$fiber = new Fiber[function []: void {
    $value = Fiber::suspend['fiber'];
    echo "Đã resume。$value: ", $value, "\n";
}];

$value = $fiber->start[];

echo "Đã tạm dừng。$value: ", $value, "\n";

$fiber->resume['test'];

// Kết quả chạy
Đã tạm dừng。$value: fiber
Đã resume。$value: test

vòng lặp sự kiện

Sau đây là một ví dụ về vòng lặp sự kiện rất đơn giản. Thăm dò soclet để nhận dữ liệu, rồi gọi lại khi có thể. vòng lặp sự kiện này chỉ cho phép khởi động lại Fiber khi có dữ liệu trên Socket, tránh bị chặn đọc

class EventLoop
{
    private string $nextId = 'a';
    private array $deferCallbacks = [];
    private array $read = [];
    private array $streamCallbacks = [];

    public function run[]: void
    {
        while [!empty[$this->deferCallbacks] || !empty[$this->read]] {
            $defers = $this->deferCallbacks;
            $this->deferCallbacks = [];
            foreach [$defers as $id => $defer] {
                $defer[];
            }

            $this->select[$this->read];
        }
    }

    private function select[array $read]: void
    {
        $timeout = empty[$this->deferCallbacks] ? null : 0;
        if [!stream_select[$read, $write, $except, $timeout, $timeout]] {
            return;
        }

        foreach [$read as $id => $resource] {
            $callback = $this->streamCallbacks[$id];
            unset[$this->read[$id], $this->streamCallbacks[$id]];
            $callback[$resource];
        }
    }

    public function defer[callable $callback]: void
    {
        $id = $this->nextId++;
        $this->deferCallbacks[$id] = $callback;
    }

    public function read[$resource, callable $callback]: void
    {
        $id = $this->nextId++;
        $this->read[$id] = $resource;
        $this->streamCallbacks[$id] = $callback;
    }
}

[$read, $write] = stream_socket_pair[
    stripos[PHP_OS, 'win'] === 0 ? STREAM_PF_INET : STREAM_PF_UNIX,
    STREAM_SOCK_STREAM,
    STREAM_IPPROTO_IP
];

// Đưa stream vào chế độ non proxy 
stream_set_blocking[$read, false];
stream_set_blocking[$write, false];

$loop = new EventLoop;

// Khi có thể đọc stream, lại khởi động việc đọc data bằng 1 cái Fiber khác nữa 
$fiber = new Fiber[function [] use [$loop, $read]: void {
    echo "Waiting for data...\n";

    $fiber = Fiber::this[];
    $loop->read[$read, fn[] => $fiber->resume[]];
    Fiber::suspend[];

    $data = fread[$read, 8192];

    echo "Received data: ", $data, "\n";
}];

// Chạy Fiber。
$fiber->start[];

// Đọc data bằng call back 
$loop->defer[fn[] => fwrite[$write, "Hello, world!"]];

// Chạy event loop
$loop->run[];

Kết quả

Waiting for data...
Received data: Hello, world!

Hình dưới đây để xem luồng thực thi giữa Main thread và Fiber Luồng thực thi đi qua lại mỗi khi bạn gọi Fiber. pause[] và Fiber->resume[]

amphp Phần sau sử dụng framework không đồng bộ amphp v3, và tôi sẽ viết 1 ví dụ mà code không đồng bộ được viết như code đồng bộ

amphp v3 xây dựng một Coroutine để thực hiện nhiều chức năng khác nhau và Promise, code để xử lý không đồng bộ trên ,, Fiber API bằng cách sử dụng vòng lặp sự kiện. Người dùng amphp v3 không cần trực tiếp sử dụng chuỗi API. Framework sẽ thực hiện công việc xử lý các đăng ký đó và tạm dừng đối với Fiber, nếu cần. Do đó, trong các khuôn khổ tương tự khác nhau, bạn có thể phải tạo và sử dụng như thế nào khác nhau một chút

Hàm defer [có thể gọi lại $callback,mixed. $ args] đăng ký Fiber after will be thuc thi khi Fiber hiện tại đã bị dừng hoặc kết thúc thời gian tạm thời. độ trễ [int $ mili giây], mili giây khi FIber hiện tại bị ngắt quãng


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}
0

amphp phần 2

Để hiển thị cách vòng lặp sự kiện chạy trong khi chuỗi chính bị tạm dừng, tôi sẽ đưa ra một ví dụ khác bằng cách sử dụng amphp v3. đang chờ [Lời hứa $ lời hứa] sẽ tiếp tục thi cho đến khi các đối số Lời hứa được giải quyết. And async [có thể gọi lại $ callback,mixed. $ args] return a Promise object


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}
1

Máy phát điện

Fiber có thể bị tạm dừng khi gọi PHP VM, vì vậy bạn cũng có thể tạo các trình tạo và trình lặp không đồng bộ. Ví dụ dưới đây sử dụng amphp v3 để tạm dừng Fiber trong Generator. Khi vòng lặp qua Trình tạo, vòng lặp foreach tạm dừng trong khi chờ giá trị trả về của Trình tạo


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}
2

ReactPHP Cuối cùng là một ví dụ về việc xác định một hàm đang chờ bằng cách sử dụng ReactPHP


final class ReflectionFiber
{
    /**
     * @param Fiber Fiber object
     */
    public function __construct[Fiber $fiber] {}

    /**
     * @return Fiber Fiber object
     */
    public function getFiber[]: Fiber {}

    /**
     * @return string  Tên file của Fiber đang chạy 
     */Nếu tạm dừng thì là 
    public function getExecutingFile[]: string {}

    /**
     * @return int Số dòng của Fiber đang chạy 
     */
    public function getExecutingLine[]: int {}

    /**
     * Giống với tham số của @param int $options debug_backtrace[]
     *
     *  @return array Backtrace của Fiber 。Giống debug_backtrace[] và ReflectionGenerator::getTrace[].
     */
    public function getTrace[int $options = DEBUG_BACKTRACE_PROVIDE_OBJECT]: array {}

    /**
     * @return bool Nếu đã bắt đầu thì là true
     */
    public function isStarted[]: bool {}

    /**
     * @return bool Nếu tạm dừng thì là true
     */
    public function isSuspended[]: bool {}

    /**
     * @return bool Nếu đang chạy thì là true
     */
    public function isRunning[]: bool {}

    /**
     * @return bool Nếu chưa xong thì là true
     */
    public function isTerminated[]: bool {}
}
3

Bản demo tích hợp ReactPHP và Fiber được thực hiện trong trowski / Reac-fiber

**FAQ **Mục tiêu của tính năng này là ai?

Chất xơ là một tính năng nâng cao mà hầu hết người dùng không sử dụng trực tiếp. Nó chủ yếu nhắm mục tiêu đến các tác giả Framework Library , những người cung cấp vòng lặp sự kiện và các API không đồng bộ. Fiber cho phép bạn khai thác liền mạch mã không đồng bộ vào mã đồng bộ hiện có của mình tại bất kỳ thời điểm nào mà không cần thay đổi ngăn xếp cuộc gọi của ứng dụng hoặc thực hiện các thay đổi mã lớn

Fiber is not In target target sử dụng trực tiếp ở cấp độ ứng dụng. Fiber là một API kiểm tra luồng cấp thấp hơn cung cấp mức độ ghi đối tượng cao để sử dụng trong mã ứng dụng. Trong một trường hợp tương tự, FFI là một phần của tính năng được thêm vào PHP gần đây, nhưng hầu hết người dùng không sử dụng trực tiếp. Tuy nhiên, người dùng có thể được hưởng rất nhiều lợi ích từ các thư viện mà họ đang sử dụng

Còn về hiệu suất thì sao?

Chuyển đổi giữa các sợi nhẹ và tùy thuộc vào nền tảng, chỉ thay đổi khoảng 20 con trỏ. Việc chuyển đổi ngữ cảnh thực thi trên máy ảo PHP tương tự như Trình tạo, nó cũng chỉ thay đổi một vài con trỏ

Những nền tảng hỗ trợ nào?

Fiber được hỗ trợ hầu hết trên các CPU hiện đại như x86, x86_64, ARM, PPC, MIPS, Windows [bất kể kiến ​​trúc nào vì nó cung cấp API Fiber] và Posix cũ hơn với hỗ trợ ucontext

Các stack thực thi được thay đổi như thế nào?

Mỗi luồng giữ các con trỏ đến ngăn xếp C và ngăn xếp VM. Enter Fiber will change stack C current at. stack VM được sao lưu trong bộ nhớ và sẽ được phục hồi khi Fiber thoát. debug_backtrace[] and backtrace outException only THEO THEO FIBER HIỆN TẠI. Nó không theo dõi Fiber bên trong Fiber

Mã chặn ảnh hưởng như thế nào đến chủ đề ?

Mã chặn [không giới hạn như file_get_contents[]] sẽ tiếp tục chặn toàn bộ quá trình, ngay cả với các chủ đề khác. Để đạt được cả hiệu suất và tính đồng thời, bạn cần viết mã của mình để sử dụng IO không đồng bộ, vòng lặp sự kiện và luồng. Đã có một số thư viện IO không đồng bộ, nhưng chúng có thể được tích hợp với mã đồng bộ bằng cách tận dụng Fiber

Fiber could be used IO does not ĐỒNG BỘ MỘT CÁCH RÕ RÀNG, vì vậy bạn có thể thay thế khai thác bằng khai thác không ngăn chặn. Nó không ảnh hưởng đến toàn bộ ngăn xếp cuộc gọi. Khi vòng lặp sự kiện nội bộ được phát triển khai trong tương lai, có thể đặt các chức năng của bộ nội bộ như chế độ ngủ [] không chặn theo mặc định

Làm thế nào để các chủ đề khác nhau truy cập vào cùng một bộ nhớ?

Tất cả các chủ đề đều nằm trong một chủ đề. Chỉ một luồng có thể chạy tại một thời điểm, vì vậy không giống như các luồng có thể thay đổi bộ nhớ cùng một lúc, nhiều luồng không thể truy cập hoặc thay đổi bộ nhớ cùng một lúc

Khi Fiber bị tạm dừng / liên tục, nhiều Fiber đang truy cập vào cùng một bộ nhớ sẽ bị xen kẽ. Do đó, một Fiber đang chạy có thể thay đổi bộ nhớ được sử dụng bởi một Fiber bị treo khác. Có các phương pháp như mutexes, semaphores, gói bộ nhớ và kênh để giải quyết vấn đề này. Chúng không được cung cấp trong RFC này vì chúng có thể được khai thác dựa trên người dùng bằng API Fiber

Tại sao lại thêm điều này vào PHP Core ?

Bằng cách bổ sung tính năng này trực tiếp vào PHP Core , tất cả các máy chủ cung cấp PHP sẽ có thể sử dụng nó. Trong nhiều trường hợp, người dùng không biết máy chủ đang cung cấp tiện ích mở rộng nào, hoặc người dùng không thể hoặc không muốn thêm bất kỳ tiện ích mở rộng nào theo ý muốn. Nếu Fiber được bao gồm trong PHP Core , bất kỳ tác giả thư viện nào cũng có thể sử dụng Fiber mà không cần lắng nghe về tính di động

Tại sao không thêm vòng lặp sự kiện và API không đồng bộ / chờ đợi vào lõi?

RFC này chỉ đề xuất chức năng tối thiểu cho phép mã người dùng cung cấp các chuỗi điều chỉnh và chuỗi màu xanh lá cây đầy đủ ngăn xếp. Có một số khung công tác cung cấp vòng lặp sự kiện, lời chúc và các API không đồng bộ khác nhau của riêng họ, nhưng các API thiết kế của họ rất đa dạng và có các thông số kỹ thuật khác nhau. Các API không đồng bộ được thiết kế cho những công cụ như cầu có thể không được bao phủ bởi các vòng lặp sự kiện được phát triển khai thác trong PHP Core

RFC tuyên bố rằng tốt nhất là cung cấp chức năng tối thiểu hóa cốt lõi và cho phép người dùng phát triển khai thác bất kỳ thành phần nào theo ý muốn. Nếu nhiều khuôn khổ được tổng hợp thành một vòng lặp sự kiện API hoặc nếu có yêu cầu có một vòng lặp sự kiện trong PHP Core , chúng tôi có thể giới thiệu chúng trong RFC tiếp theo. RFC này không ngăn bạn thêm async/await hoặc các vòng lặp sự kiện vào PHP Core của bạn trong tương lai

Đề xuất này khác với đề xuất Fiber trước đây như thế nào?

Các Fiber RFC được xuất bản trước đây không hỗ trợ chuyển đổi ngữ cảnh trong các hàm nội bộ [array_map, preg_replace_callback, v. v. ] hoặc các trình xử lý opcache [foreach, output, v. v. ]. Do đó, việc sử dụng mã người dùng được gọi từ mã C hoặc tiện ích mở rộng ghi đè zend_execute_ex, chẳng hạn như Xdebug, có thể bị lỗi

Chủ Đề