🧵 Fibers em PHP 8.1+

Fibers são uma funcionalidade nativa introduzida no PHP 8.1 que permite pausar e retomar a execução de código sem bloquear todo o processo. Elas são a base para implementar concorrência cooperativa e frameworks assíncronos em PHP puro, sem necessidade de extensões externas.

🎯 Importante: Este guia cobre apenas a classe Fiber nativa do PHP 8.1+. Para o conceito mais amplo de coroutines, veja Coroutines em PHP.


📚 Índice

  1. O que são Fibers?
  2. Estados de uma Fiber
  3. API Completa
  4. Criando e Executando Fibers
  5. Comunicação Bidirecional
  6. Tratamento de Exceções
  7. Construindo um Agendador
  8. Exemplos Práticos
  9. Boas Práticas
  10. Limitações e Quando Usar

🎓 O que são Fibers?

O Problema: Código Bloqueante

<?php
// ❌ Código bloqueante tradicional
function task1() {
    echo "Task 1: Início\n";
    sleep(2); // BLOQUEIA todo o programa por 2s
    echo "Task 1: Fim\n";
}

function task2() {
    echo "Task 2: Início\n";
    sleep(1); // BLOQUEIA todo o programa por 1s
    echo "Task 2: Fim\n";
}

$start = microtime(true);
task1(); // Espera 2s
task2(); // Espera 1s
$duration = microtime(true) - $start;

echo "Tempo total: " . round($duration) . "s\n";

// Saída esperada
// Task 1: Início
// Task 1: Fim
// Task 2: Início
// Task 2: Fim
// Tempo total: 3s

Problema: Enquanto task1() dorme, não podemos executar task2(). Desperdiçamos 3 segundos quando poderíamos usar apenas 2s.

A Solução: Fibers

<?php
// ✅ Com Fibers - execução intercalada
$fiber1 = new Fiber(function() {
    echo "Fiber 1: Passo 1\n";
    Fiber::suspend(); // Pausa e libera controle
    echo "Fiber 1: Passo 2\n";
});

$fiber2 = new Fiber(function() {
    echo "Fiber 2: Passo 1\n";
    Fiber::suspend(); // Pausa e libera controle
    echo "Fiber 2: Passo 2\n";
});

// Execução intercalada
$fiber1->start();  // "Fiber 1: Passo 1" → pausa
$fiber2->start();  // "Fiber 2: Passo 1" → pausa
$fiber1->resume(); // "Fiber 1: Passo 2" → termina
$fiber2->resume(); // "Fiber 2: Passo 2" → termina

// Saída esperada
// Fiber 1: Passo 1
// Fiber 2: Passo 1
// Fiber 1: Passo 2
// Fiber 2: Passo 2

Vantagem: Podemos pausar fiber1, executar fiber2, e retomar fiber1 depois, aproveitando melhor o tempo.


🔄 Estados de uma Fiber

Uma Fiber passa por diferentes estados durante seu ciclo de vida:

┌─────────────────┐
│  NÃO INICIADA   │
│ isStarted()=false│
└────────┬────────┘
         │ start()
         ↓
┌─────────────────┐
│   EXECUTANDO    │
│ isRunning()=true │
└────────┬────────┘
         │ Fiber::suspend()
         ↓
┌─────────────────┐
│    SUSPENSA     │
│isSuspended()=true│
└────────┬────────┘
         │ resume()
         ↓
┌─────────────────┐
│   EXECUTANDO    │
└────────┬────────┘
         │ return / exceção / fim
         ↓
┌─────────────────┐
│   TERMINADA     │
│isTerminated()=true│
└─────────────────┘

Exemplo Completo de Estados

<?php
$fiber = new Fiber(function() {
    echo "Executando...\n";
    Fiber::suspend();
    echo "Retomado...\n";
    return "Finalizado!";
});

// Estado inicial: NÃO INICIADA
echo "Estado inicial:\n";
var_dump($fiber->isStarted());     // false
var_dump($fiber->isRunning());     // false
var_dump($fiber->isSuspended());   // false
var_dump($fiber->isTerminated());  // false

// Inicia a Fiber
$fiber->start();

// Estado: SUSPENSA (pausou em Fiber::suspend())
echo "\nApós start():\n";
var_dump($fiber->isStarted());     // true
var_dump($fiber->isSuspended());   // true
var_dump($fiber->isTerminated());  // false

// Retoma a Fiber
$result = $fiber->resume();

// Estado: TERMINADA
echo "\nApós resume():\n";
var_dump($fiber->isTerminated());  // true
var_dump($result);                 // string(11) "Finalizado!"

// Saída esperada
// Estado inicial:
// bool(false)
// bool(false)
// bool(false)
// bool(false)
// Executando...
// 
// Após start():
// bool(true)
// bool(true)
// bool(false)
// Retomado...
// 
// Após resume():
// bool(true)
// NULL

📋 API Completa

Métodos de Instância

<?php
$fiber = new Fiber(callable $callback);

// Iniciar execução
$fiber->start(mixed ...$args): mixed;

// Retomar execução (quando suspensa)
$fiber->resume(mixed $value = null): mixed;

// Lançar exceção dentro da Fiber
$fiber->throw(Throwable $exception): mixed;

// Verificar estados
$fiber->isStarted(): bool;     // Já foi iniciada?
$fiber->isSuspended(): bool;   // Está pausada?
$fiber->isRunning(): bool;     // Está executando AGORA?
$fiber->isTerminated(): bool;  // Já terminou?

Métodos Estáticos (dentro de uma Fiber)

<?php
// Obter a Fiber atualmente em execução
Fiber::getCurrent(): ?Fiber;

// Suspender a Fiber atual
Fiber::suspend(mixed $value = null): mixed;

Exemplo da API

<?php
$fiber = new Fiber(function(string $name): string {
    echo "Olá, $name!\n";

    $received = Fiber::suspend("Primeira pausa");
    echo "Recebi: $received\n";

    $received = Fiber::suspend("Segunda pausa");
    echo "Recebi: $received\n";

    return "Tchau, $name!";
});

// start() - inicia com argumentos
$value = $fiber->start("João");
echo "Fiber retornou: $value\n";

### Exemplo 1: Fiber Simples

```php
<?php
// Criar uma Fiber
$fiber = new Fiber(function(): void {
    echo "Linha 1\n";
    echo "Linha 2\n";
    echo "Linha 3\n";
});

// Iniciar execução
$fiber->start();

echo "Fiber terminou!\n";

// Saída esperada
// Linha 1
// Linha 2
// Linha 3
// Fiber terminou!

Exemplo 2: Passando Argumentos

<?php
$fiber = new Fiber(function(int $a, int $b): int {
    $sum = $a + $b;
    echo "Somando $a + $b = $sum\n";
    return $sum;
});

// Passa argumentos via start()
$fiber->start(5, 3);
echo "Concluído\n";

// Saída esperada
// Somando 5 + 3 = 8
// Concluído

Exemplo 3: Múltiplas Pausas

<?php
$fiber = new Fiber(function(): void {
    for ($i = 1; $i <= 5; $i++) {
        echo "Contador: $i\n";

        // Pausa após cada número (exceto o último)
        if ($i < 5) {
            Fiber::suspend();
        }
    }
});

$fiber->start(); // Imprime 1 e pausa

echo "--- Fazendo outras coisas ---\n";

// Retoma 4 vezes para completar
while (!$fiber->isTerminated()) {
    $fiber->resume();
}

echo "Concluído!\n";

// Saída esperada
// Contador: 1
// --- Fazendo outras coisas ---
// Contador: 2
// Contador: 3
// Contador: 4
// Contador: 5
// Concluído!

Exemplo 4: Retornando Valores

<?php
$fiber = new Fiber(function(): array {
    echo "Processando...\n";
    Fiber::suspend();

    echo "Finalizando...\n";

    return ['status' => 'success', 'data' => [1, 2, 3]];
});

$fiber->start();
echo "Fiber pausada\n";

$fiber->resume();
echo "Concluído\n";

// Saída esperada
// Processando...
// Fiber pausada
// Finalizando...
// Concluído

🔄 Comunicação Bidirecional

A verdadeira potência das Fibers está na comunicação bidirecional: podemos enviar valores PARA a Fiber e receber valores DE VOLTA.

Enviando para a Fiber

<?php
$fiber = new Fiber(function(): void {
    // suspend() retorna o valor passado em resume()
    $value1 = Fiber::suspend();
    echo "Recebi: $value1\n";

    $value2 = Fiber::suspend();
    echo "Recebi: $value2\n";
});

$fiber->start();

// Envia valores ao retomar
$fiber->resume("Olá");
$fiber->resume("Mundo");

// Saída esperada
// Recebi: Olá
// Recebi: Mundo

Recebendo da Fiber

<?php
$fiber = new Fiber(function(): void {
    // suspend() ENVIA um valor para quem chamou resume()
    Fiber::suspend("Mensagem 1");
    Fiber::suspend("Mensagem 2");
    Fiber::suspend("Mensagem 3");
});

$fiber->start();

$fiber->resume();
echo "Recebi: Mensagem 1\n";

$fiber->resume();
echo "Recebi: Mensagem 2\n";

$fiber->resume();
echo "Recebi: Mensagem 3\n";

// Saída esperada
// Recebi: Mensagem 1
// Recebi: Mensagem 2
// Recebi: Mensagem 3

Comunicação Completa (Bidirecional)

<?php
$echo = new Fiber(function(): void {
    for ($i = 0; $i < 2; $i++) {
        // Recebe mensagem e ecoa de volta em maiúsculas
        $message = Fiber::suspend("Pronto para receber");
        $response = strtoupper($message);
        Fiber::suspend($response);
    }
});

$echo->start();

// Primeira mensagem
$echo->resume();
echo "Pronto para receber\n";

$echo->resume("hello");
echo "Resposta: HELLO\n";

// Segunda mensagem
$echo->resume();
echo "Pronto para receber\n";

$echo->resume("world");
echo "Resposta: WORLD\n";

// Saída esperada
// Pronto para receber
// Resposta: HELLO
// Pronto para receber
// Resposta: WORLD

Exemplo: Processador Simples

<?php
$processor = new Fiber(function(): void {
    // Operação 1
    $op = Fiber::suspend();
    $a = Fiber::suspend();
    $b = Fiber::suspend();

    $result = match($op) {
        '+' => $a + $b,
        '-' => $a - $b,
        '*' => $a * $b,
        '/' => $b != 0 ? $a / $b : 0,
        default => 0
    };

    Fiber::suspend("Resultado: $result");

    // Operação 2
    $op = Fiber::suspend();
    $a = Fiber::suspend();
    $b = Fiber::suspend();

    $result = match($op) {
        '+' => $a + $b,
        '-' => $a - $b,
        '*' => $a * $b,
        '/' => $b != 0 ? $a / $b : 0,
        default => 0
    };

    Fiber::suspend("Resultado: $result");
});

$processor->start();

// Operação 1: 10 + 5
$processor->resume('+');
$processor->resume(10);
$processor->resume(5);
$processor->resume();
echo "Resultado: 15\n";

// Operação 2: 20 / 4
$processor->resume('/');
$processor->resume(20);
$processor->resume(4);
$processor->resume();
echo "Resultado: 5\n";

// Saída esperada
// Resultado: 15
// Resultado: 5

⚠️ Tratamento de Exceções

Exceções Dentro da Fiber

<?php
$fiber = new Fiber(function() {
    echo "Iniciando...\n";

    throw new Exception("Erro dentro da Fiber!");

    echo "Esta linha nunca executa\n";
});

try {
    $fiber->start();
} catch (Exception $e) {
    echo "Capturei: {$e->getMessage()}\n";
}

echo "Programa continua normalmente\n";

// Saída esperada
// Iniciando...
// Capturei: Erro dentro da Fiber!
// Programa continua normalmente

Lançando Exceções NA Fiber

O método throw() permite lançar uma exceção dentro de uma Fiber suspensa:

<?php
$fiber = new Fiber(function() {
    echo "Passo 1\n";

    try {
        Fiber::suspend();
        echo "Passo 2 (não executado)\n";
    } catch (Exception $e) {
        echo "Capturei dentro da Fiber: {$e->getMessage()}\n";
    }

    echo "Passo 3\n";
});

$fiber->start(); // Executa até suspend()

// Lança exceção DENTRO da Fiber
$fiber->throw(new Exception("Erro externo!"));

// Saída esperada
// Passo 1
// Capturei dentro da Fiber: Erro externo!
// Passo 3

Exemplo: Tratamento Robusto

<?php
class Task {
    private Fiber $fiber;
    private string $name;

    public function __construct(string $name, callable $callback) {
        $this->name = $name;
        $this->fiber = new Fiber($callback);
    }

    public function run(): void {
        try {
            if (!$this->fiber->isStarted()) {
                echo "[{$this->name}] Iniciando...\n";
                $this->fiber->start();
            } else if ($this->fiber->isSuspended()) {
                echo "[{$this->name}] Retomando...\n";
                $this->fiber->resume();
            }
        } catch (Throwable $e) {
            echo "[{$this->name}] ERRO: {$e->getMessage()}\n";
        }

        if ($this->fiber->isTerminated()) {
            echo "[{$this->name}] ✓ Concluída\n";
        }
    }
}

$task = new Task("MinhaTask", function() {
    echo "Executando passo 1\n";
    Fiber::suspend();

    echo "Executando passo 2\n";
    throw new RuntimeException("Algo deu errado!");

    echo "Passo 3 (nunca executado)\n";
});

$task->run(); // Passo 1
$task->run(); // Passo 2 + erro

// Saída esperada
// [MinhaTask] Iniciando...
// Executando passo 1
// [MinhaTask] Retomando...
// Executando passo 2
// [MinhaTask] ERRO: Algo deu errado!
// [MinhaTask] ✓ Concluída

🎯 Construindo um Agendador

Para gerenciar múltiplas Fibers de forma eficiente, precisamos de um Scheduler (agendador):

Agendador Básico

<?php
class BasicScheduler {
    private array $fibers = [];

    public function add(Fiber $fiber): void {
        $this->fibers[] = $fiber;
    }

    public function run(): void {
        // Inicia todas as Fibers
        foreach ($this->fibers as $fiber) {
            if (!$fiber->isStarted()) {
                $fiber->start();
            }
        }

        // Loop principal: retoma Fibers suspensas
        while ($this->hasActiveFibers()) {
            foreach ($this->fibers as $fiber) {
                if ($fiber->isSuspended()) {
                    $fiber->resume();
                }
            }
        }
    }

    private function hasActiveFibers(): bool {
        foreach ($this->fibers as $fiber) {
            if (!$fiber->isTerminated()) {
                return true;
            }
        }
        return false;
    }
}

// Exemplo de uso
$scheduler = new BasicScheduler();

$scheduler->add(new Fiber(function() {
    for ($i = 1; $i <= 3; $i++) {
        echo "Task A - $i\n";
        Fiber::suspend();
    }
}));

$scheduler->add(new Fiber(function() {
    for ($i = 1; $i <= 3; $i++) {
        echo "Task B - $i\n";
        Fiber::suspend();
    }
}));

$scheduler->run();

// Saída esperada
// Task A - 1
// Task B - 1
// Task A - 2
// Task B - 2
// Task A - 3
// Task B - 3

Agendador com Sleep Assíncrono

<?php
class AsyncScheduler {
    private array $fibers = [];
    private array $sleeping = []; // ['fiber' => Fiber, 'wakeTime' => float]

    public function spawn(callable $callback): void {
        $this->fibers[] = new Fiber($callback);
    }

    public function sleep(float $seconds): void {
        $fiber = Fiber::getCurrent();
        if ($fiber === null) {
            throw new RuntimeException("sleep() deve ser chamado dentro de uma Fiber");
        }

        $this->sleeping[] = [
            'fiber' => $fiber,
            'wakeTime' => microtime(true) + $seconds
        ];

        Fiber::suspend();
    }

    public function run(): void {
        // Inicia todas
        foreach ($this->fibers as $fiber) {
            $fiber->start();
        }

        // Loop principal
        while ($this->hasActiveFibers()) {
            $this->wakeUpFibers();

            foreach ($this->fibers as $fiber) {
                if ($fiber->isSuspended() && !$this->isSleeping($fiber)) {
                    $fiber->resume();
                }
            }

            usleep(1000); // 1ms - evita 100% CPU
        }
    }

    private function wakeUpFibers(): void {
        $now = microtime(true);

        foreach ($this->sleeping as $i => $sleep) {
            if ($now >= $sleep['wakeTime']) {
                $sleep['fiber']->resume();
                unset($this->sleeping[$i]);
            }
        }

        $this->sleeping = array_values($this->sleeping);
    }

    private function isSleeping(Fiber $fiber): bool {
        foreach ($this->sleeping as $sleep) {
            if ($sleep['fiber'] === $fiber) {
                return true;
            }
        }
        return false;
    }

    private function hasActiveFibers(): bool {
        foreach ($this->fibers as $fiber) {
            if (!$fiber->isTerminated()) {
                return true;
            }
        }
        return count($this->sleeping) > 0;
    }
}

// Exemplo de uso
$scheduler = new AsyncScheduler();

$scheduler->spawn(function() use ($scheduler) {
    echo "[Task 1] Início\n";
    $scheduler->sleep(1);
    echo "[Task 1] Após 1s\n";
    $scheduler->sleep(0.5);
    echo "[Task 1] Fim\n";
});

$scheduler->spawn(function() use ($scheduler) {
    echo "[Task 2] Início\n";
    $scheduler->sleep(0.5);
    echo "[Task 2] Após 0.5s\n";
    $scheduler->sleep(1);
    echo "[Task 2] Fim\n";
});

$start = microtime(true);
$scheduler->run();
$duration = microtime(true) - $start;

echo "\nConcluído em " . round($duration, 2) . "s\n";

// Saída esperada (horários aproximados)
// [Task 1] Início
// [Task 2] Início
// [Task 2] Após 0.5s
// [Task 1] Após 1s
// [Task 1] Fim
// [Task 2] Fim
// 
// Concluído em 1.5s

Observe: As tarefas executam concorrentemente! Total de 1.5s ao invés de 3s.


💡 Exemplos Práticos

1. Gerador de Fibonacci

<?php
function fibonacci(): Fiber {
    return new Fiber(function(): void {
        $a = 0;
        $b = 1;

        Fiber::suspend($a);
        Fiber::suspend($b);

        for ($i = 0; $i < 8; $i++) {
            $next = $a + $b;
            $a = $b;
            $b = $next;
            Fiber::suspend($next);
        }
    });
}

$fib = fibonacci();
$fib->start();

echo "Fibonacci: ";
$fib->resume();
echo "0 ";
while (!$fib->isTerminated()) {
    $value = $fib->resume();
    if ($value !== null) {
        echo "$value ";
    }
}
echo "\n";

//Saída esperada
// Fibonacci: 0 1 1 2 3 5 8 13 21 34 

2. Processador de Tarefas em Lote

<?php
function batchProcessor(array $items, int $batchSize): Fiber {
    return new Fiber(function() use ($items, $batchSize): void {
        $batches = array_chunk($items, $batchSize);

        foreach ($batches as $i => $batch) {
            echo "Processando lote " . ($i + 1) . " de " . count($batches) . "\n";

            foreach ($batch as $item) {
                echo "  - Processando: $item\n";
            }

            // Pausa após cada lote
            if ($i < count($batches) - 1) {
                Fiber::suspend("Lote " . ($i + 1) . " completo");
            }
        }
    });
}

$items = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$processor = batchProcessor($items, 3);

$processor->start();

while (!$processor->isTerminated()) {
class HttpSimulator {
    private AsyncScheduler $scheduler;

    public function __construct(AsyncScheduler $scheduler) {
        $this->scheduler = $scheduler;
    }

    public function fetch(string $url): array {
        echo "  → GET $url\n";

        // Simula latência de rede (100-300ms)
        $latency = rand(100, 300) / 1000;
        $this->scheduler->sleep($latency);

        echo "  ← 200 OK $url\n";

        return [
            'url' => $url,
            'status' => 200,
            'body' => "Conteúdo de $url"
        ];
    }
}

$scheduler = new AsyncScheduler();
$http = new HttpSimulator($scheduler);

$urls = [
    'https://api.exemplo.com/users',
    'https://api.exemplo.com/posts',
    'https://api.exemplo.com/comments',
];

$results = [];

foreach ($urls as $url) {
    $scheduler->spawn(function() use ($http, $url, &$results) {
        $response = $http->fetch($url);
        $results[] = $response;
        echo "[✓] Concluído: {$response['url']}\n";
    });
}

echo "Buscando " . count($urls) . " URLs...\n";

$start = microtime(true);
$scheduler->run();
$duration = microtime(true) - $start;

echo "\n✅ " . count($results) . " requisições em " . round($duration, 2) . "s\n";

// Saída esperada (ordem pode variar)
// Buscando 3 URLs...
//   → GET https://api.exemplo.com/users
//   → GET https://api.exemplo.com/posts
//   → GET https://api.exemplo.com/comments
//   ← 200 OK https://api.exemplo.com/users
// [✓] Concluído: https://api.exemplo.com/users
//   ← 200 OK https://api.exemplo.com/posts
// [✓] Concluído: https://api.exemplo.com/posts
//   ← 200 OK https://api.exemplo.com/comments
// [✓] Concluído: https://api.exemplo.com/comments
// 
// ✅ 3 requisições em 0.3s

✅ Boas Práticas

1. Sempre Verifique o Estado

<?php
$fiber = new Fiber(function() {
    Fiber::suspend();
});

$fiber->start();

// ✅ BOM: Verificar antes de resumir
if ($fiber->isSuspended()) {
    $fiber->resume();
}

// ❌ RUIM: Pode causar FiberError
// $fiber->resume(); // Erro se já terminou!

2. Use Type Hints

<?php
// ✅ BOM: Type hints claros
function createCounter(): Fiber {
    return new Fiber(function(): Generator {
        $count = 0;
        while (true) {
            yield Fiber::suspend(++$count);
        }
    });
}

3. Documente Pontos de Suspensão

<?php
/**
 * Busca dados do usuário
 * 
 * @param int $userId
 * @return array
 * 
 * @suspends Suspende durante a requisição HTTP
 */
function fetchUser(int $userId): array {
    Fiber::suspend(); // Ponto de suspensão documentado
    return ['id' => $userId, 'name' => 'User'];
}

4. Evite Estado Compartilhado

<?php
// ❌ RUIM: Estado compartilhado
$shared = 0;

$fiber1 = new Fiber(function() use (&$shared) {
    $shared++; // Pode dar problema!
});

// ✅ BOM: Comunicação explícita
$fiber2 = new Fiber(function(): int {
    $count = 0;
    while (true) {
        $count++;
        Fiber::suspend($count);
    }
});

5. Trate Exceções

<?php
function safeRun(Fiber $fiber): void {
    try {
        if (!$fiber->isStarted()) {
            $fiber->start();
        } else if ($fiber->isSuspended()) {
            $fiber->resume();
        }
    } catch (Throwable $e) {
        echo "Erro: {$e->getMessage()}\n";
    }
}

⚠️ Limitações e Quando Usar

Fibers NÃO São Threads

<?php
// ❌ Fibers NÃO executam em paralelo real
// Apenas intercalam execução em um único thread

$fiber1 = new Fiber(function() {
    // Cálculo pesado - NÃO se beneficia de Fibers
    for ($i = 0; $i < 10000000; $i++) {
        $x = sqrt($i);
    }
});

Use Fibers Para:

✅ Operações I/O-bound (rede, disco, banco de dados) ✅ Implementar event loops ✅ Múltiplas requisições HTTP simultâneasGeradores complexos com estado ✅ Concorrência cooperativa

NÃO Use Fibers Para:

❌ Tarefas CPU-bound (cálculos matemáticos pesados) ❌ Código síncrono simples que já funciona bem ❌ Quando paralelismo real é necessário (use processos/threads)

Comparação: Síncrono vs Fibers

<?php
// ❌ Síncrono - 3 segundos
function syncTasks() {
    sleep(1); // Task 1
    sleep(1); // Task 2
    sleep(1); // Task 3
    // Total: 3s
}

// ✅ Com Fibers - 1 segundo (concorrente)
function asyncTasks() {
    $scheduler = new AsyncScheduler();

    $scheduler->spawn(fn() => $scheduler->sleep(1)); // Task 1
    $scheduler->spawn(fn() => $scheduler->sleep(1)); // Task 2
    $scheduler->spawn(fn() => $scheduler->sleep(1)); // Task 3

    $scheduler->run();
    // Total: ~1s (executam "juntas")
}

🎓 Resumo

Conceitos-Chave

  • Fiber = Unidade de execução que pode ser pausada e retomada
  • suspend() = Pausa a Fiber atual
  • resume() = Retoma uma Fiber suspensa
  • Comunicação bidirecional = Enviar e receber valores
  • Concorrência cooperativa = Múltiplas tarefas progredindo alternadamente

Fluxo Típico

<?php
// 1. Criar
$fiber = new Fiber(function() {
    // 3. Executar até suspend()
    Fiber::suspend();
    // 5. Continuar até o fim
});

// 2. Iniciar
$fiber->start();

// 4. Retomar
$fiber->resume();

API Essencial

<?php
new Fiber(callable $callback)
$fiber->start(mixed ...$args): mixed
$fiber->resume(mixed $value = null): mixed
$fiber->throw(Throwable $exception): mixed

Fiber::getCurrent(): ?Fiber
Fiber::suspend(mixed $value = null): mixed

$fiber->isStarted(): bool
$fiber->isSuspended(): bool
$fiber->isRunning(): bool
$fiber->isTerminated(): bool

🔗 Recursos Relacionados


Fibers são a base para programação assíncrona moderna em PHP! 🚀