Fibers

Fiberlere giriş

(PHP 8 >= 8.1.0)

Fiberler, tamamen yığıtlanabilen ve yürütmeyi kesintiye uğratılabilen işlevlerdir. Fiberin çağrı yığıtının herhangi bir yerinde askıya alınmasıyla yürütmenin bekletilmesi ve daha sonra fiberin yürütmeyi kaldığı yerden devam ettirmesi sağlanabilir.

Fiberler icra yığıtınını tamamını bekletebilir, böylece işlevin davranışını değiştirmek için işlevin doğrudan çağrılması gerekmez.

Fiber::suspend() çağrısı ile çağrı yığıtının herhangi bir yerinde yürütme kesintiye uğratılabilir (yani, Fiber::suspend() oldukça iç içe çağrıların derinlerinde yer alabileceği gibi hiçbir yerde de var olmayabilir).

Yığıtsız üreteçlerin (Generator) tersine, her Fiber sınıfının kendi çağrı yığıtı vardır. Böylece, oldukça iç içe işlev çağrılarında bile bekletme sağlanabilmektedir. Bir kesinti noktası belirten bir işlev (yani, Fiber::suspend() çağrısı), Fiber::suspend() dönüş türünün değiştirilmemesini gerektirir (bir Generator örneğinden dönen yield deyimini kullanan bir işlevin tersine).

Fiberler PHP VM içinden çağrılanlar dahil, array_map() işlevine sağlanan işlevler veya Iterator nesnesi üzerinde foreach ile çağrılan yöntemler gibi, herhangi bir işlev çağrısını askıya alabilir.

Bir kere askıya alınınca, Fiber::resume() işlevi herhangi bir değerle çağrılarak veya Fiber::throw() kullanarak fiber içinde bir istisna yavrulatarak, fiber yürütmesi kaldığı yerden devam ettirilebilir. Değer, Fiber::suspend() yönteminden veya yavrulanan istisnadan döndürülür.

Örnek 1 - Temel kullanım örneği

<?php
$fiber 
= new Fiber(function (): void {
   
$value Fiber::suspend('fiber');
   echo 
"Fiberi devam ettirmekte kullanılan değer: "$valuePHP_EOL;
});
$value $fiber->start();
echo 
"Fiber askıya alındığındaki değer: "$valuePHP_EOL;
$fiber->resume('test');
?>

Yukarıdaki örneğin çıktısı:

Fiber askıya alınırken kullanılan değer: fiber
Fiberi devam ettirmekte kullanılan değer: test
add a note add a note

User Contributed Notes 2 notes

up
2
user at csa dot es
19 days ago
Perhaps not using the same variable name everywhere will be a good idea

<?php
$fiber
= new Fiber(function (): void {
  
$parm = Fiber::suspend('fiber');
   echo
"Value used to resume fiber: ", $parm, PHP_EOL;
});

$res = $fiber->start();

echo
"Value from fiber suspending: ", $res, PHP_EOL;

$fiber->resume('test');
?>
up
1
maxpanchnko at gmail dot com
2 days ago
One of examples, how to make multi_curl faster twice (pseudocode) using Fibers:

<?php

$curlHandles
= [];
$urls = [
   
'https://example.com/1',
   
'https://example.com/2',
    ...
   
'https://example.com/1000',
];
$mh = curl_multi_init();
$mh_fiber = curl_multi_init();

$halfOfList = floor(count($urls) / 2);
foreach (
$urls as $index => $url) {
   
$ch = curl_init($url);
   
$curlHandles[] = $ch;

   
// half of urls will be run in background in fiber
   
$index > $halfOfList ? curl_multi_add_handle($mh_fiber, $ch) : curl_multi_add_handle($mh, $ch);
}

$fiber = new Fiber(function (CurlMultiHandle $mh) {
   
$still_running = null;
    do {
       
curl_multi_exec($mh, $still_running);
       
Fiber::suspend();
    } while (
$still_running);
});

// run curl multi exec in background while fiber is in suspend status
$fiber->start($mh_fiber);

$still_running = null;
do {
   
$status = curl_multi_exec($mh, $still_running);
} while (
$still_running);

do {
   
/**
     * at this moment curl in fiber already finished (maybe)
     * so we must refresh $still_running variable with one more cycle "do while" in fiber
     **/
   
$status_fiber = $fiber->resume();
} while (!
$fiber->isTerminated());

foreach (
$curlHandles as $index => $ch) {
   
$index > $halfOfList ? curl_multi_remove_handle($mh_fiber, $ch) : curl_multi_remove_handle($mh, $ch);
}
curl_multi_close($mh);
curl_multi_close($mh_fiber);
?>
To Top