Corrotinas oferecem uma abordagem de concorrência leve, gerenciada no espaço do usuário em vez de depender do escalonador do kernel do sistema operacional. Isso permite uma execução mais eficiente e menos sobrecarga.
Maneiras de Criar Corrotinas
Função co()
A função co() é um atalho conveniente para iniciar uma nova corrotina.
public function test() {
// Obtém e exibe o ID da corrotina atual (principal).
echo "ID inicial: " . Coroutine::id() . PHP_EOL;
// Cria e executa uma nova corrotina.
co(function () {
// Obtém e exibe o ID da nova corrotina.
echo "ID da corrotina: " . Coroutine::id() . PHP_EOL;
echo "Esta corrotina foi criada usando co()".PHP_EOL;
});
}
Acessando o endpoint /index/test via HTTP:
http://seu_ip:9501/index/test
Saída esperada no terminal:
ID inicial: 2
ID da corrotina: 3
Esta corrotina foi criada usando co()
Função go()
Similar à função co(), go() também inicia uma nova corrotina.
public function test() {
echo "ID principal: " . Coroutine::id() . PHP_EOL;
// Cria e executa uma nova corrotina.
go(function () {
echo "ID da corrotina: " . Coroutine::id() . PHP_EOL;
echo "Esta corrotina foi criada usando go()".PHP_EOL;
});
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal:
ID principal: 2
ID da corrotina: 3
Esta corrotina foi criada usando go()
Método Coroutine::create()
Para um controle mais explícito, o método estático Coroutine::create() pode ser utilizado.
use Hyperf\Utils\Coroutine;
public function test() {
echo "ID da corrotina principal: " . Coroutine::id() . PHP_EOL;
// Cria uma nova corrotina de forma explícita.
Coroutine::create(function() {
echo "ID da sub-corrotina: " . Coroutine::id() . PHP_EOL;
echo "Esta corrotina foi criada usando Coroutine::create()".PHP_EOL;
});
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal:
ID da corrotina principal: 2
ID da sub-corrotina: 3
Esta corrotina foi criada usando Coroutine::create()
Funções Úteis de Corrotina
Verificar se o código atual está sendo executado dentro de um ambiente de corrotina:
Hyperf\Utils\Coroutine::inCoroutine(): bool
Obter o identificador único da corrotina atual:
Hyperf\Utils\Coroutine::id()
Canal (Channel) para Comnuicação
O Channel é fundamental para a comunicação e sincronização entre corrotinas.
public function test() {
co(function () {
// Cria um canal para comunicação.
$canal = new \Swoole\Coroutine\Channel();
// Inicia uma corrotina filha para enviar dados ao canal.
co(function () use ($canal) {
$canal->push('Dados enviados pela corrotina filha');
});
// Aguarda e recupera dados do canal.
$dadosRecebidos = $canal->pop();
echo "Dados recebidos da corrotina filha: " . $dadosRecebidos;
});
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada:
Dados recebidos da corrotina filha: Dados enviados pela corrotina filha
Característica defer
O defer permite agendar a execução de uma função após a conclusão da corrotina atual, de forma semelhante a um bloco finally.
public function test() {
Coroutine::defer(function() {
echo "Primeira ação adiada".PHP_EOL;
});
Coroutine::defer(function() {
echo "Segunda ação adiada".PHP_EOL;
});
Coroutine::defer(function() {
echo "Terceira ação adiada".PHP_EOL;
});
echo 'Execução principal da corrotina'.PHP_EOL;
}
Acessando o endopint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal (a ordem das ações adiadas é invertida):
Execução principal da corrotina
Terceira ação adiada
Segunda ação adiada
Primeira ação adiada
Característica WaitGroup
WaitGroup é usado para aguardar a conclusão de um conjunto de corrotinas.
use Hyperf\Utils\WaitGroup;
public function test() {
$wg = new WaitGroup();
// Incrementa o contador para duas corrotinas.
$wg->add(2);
// Corrotina A: simula uma tarefa demorada.
co(function () use ($wg) {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Corrotina A concluída".PHP_EOL;
// Decrementa o contador ao concluir.
$wg->done();
});
// Corrotina B: simula outra tarefa demorada.
co(function () use ($wg) {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Corrotina B concluída".PHP_EOL;
// Decrementa o contador ao concluir.
$wg->done();
});
// Aguarda até que ambas as corrotinas chamem done().
$wg->wait();
echo "Todas as corrotinas foram executadas".PHP_EOL;
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal (a ordem de conclusão das corrotinas pode variar):
CorrotinaB concluída
CorrotinaA concluída
Todas as corrotinas foram executadas
Característica Parallel
A classe Parallel permite executar múltiplas corrotinas concorrentemente e coletar seus resultados.
use Hyperf\Utils\Exception\ParallelExecutionException;
use Hyperf\Utils\Coroutine;
use Hyperf\Utils\Parallel;
public function test() {
$parallel = new Parallel();
// Adiciona a primeira tarefa paralela.
$parallel->add(function () {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Tarefa A concluída".PHP_EOL;
return Coroutine::id(); // Retorna o ID da corrotina.
});
// Adiciona a segunda tarefa paralela.
$parallel->add(function () {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Tarefa B concluída".PHP_EOL;
return Coroutine::id(); // Retorna o ID da corrotina.
});
try {
// Aguarda a conclusão de todas as tarefas e coleta os resultados.
$resultados = $parallel->wait();
echo "Resultados da execução paralela:".PHP_EOL;
var_dump($resultados);
} catch(ParallelExecutionException $e) {
// Captura exceções que possam ocorrer durante a execução paralela.
var_dump($e->getResults()); // Resultados das tarefas concluídas antes da exceção.
var_dump($e->getThrowables()); // Exceções lançadas pelas corrotinas.
}
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal (a ordem de conclusão pode variar):
Tarefa B concluída
Tarefa A concluída
Resultados da execução paralela:
array(2) {
[1]=>
int(4)
[0]=>
int(3)
}
Uma versão abreviada usando a função helper parallel():
$resultados = parallel([
function () {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Tarefa A concluída".PHP_EOL;
return Coroutine::id();
},
function () {
$tempoEspera = mt_rand(1, 5);
sleep($tempoEspera);
echo "Tarefa B concluída".PHP_EOL;
return Coroutine::id();
}
]);
Contexto de Corrotina
O contexto de corrotina permite armazenar e recuperar dados associados à corrotina atual de forma segura.
use Hyperf\Context\Context;
public function test() {
co(function() {
// Define um valor no contexto da corrotina.
Context::set('nome', 'Valor Exemplo');
// Recupera o valor do contexto.
$nome = Context::get('nome');
echo $nome . PHP_EOL;
});
}
Acessando o endpoint /index/test:
http://seu_ip:9501/index/test
Saída esperada no terminal:
Valor Exemplo