Muitos idiomas modernos oferecem suporte ao trabalho com corotinas no nível do idioma. Atualmente, o Java não suporta corotinas, mas há esperança de que as coisas possam mudar no futuro.
No C ++ 20, está planejado introduzir suporte para trabalhar com corotinas.
Usando JNI, podemos escrever corotinas em C ++ e usar no código Java.
Vamos considerar quais corotinas nativas podem ser escritas e como usá-las no código Java.
O gerador permite criar uma sequência de valores de um determinado tipo, enquanto os valores são gerados de forma lenta e síncrona.
generator<int> generate(int count) { for (int i = 0; i < count; i++) { co_yield i; } }
Generator<Integer> gen1 = Coroutine.yield(5); Generator<Float> gen2 = Coroutine.yield(1f, 5); Generator<Double> gen3 = Coroutine.yield(v -> v * 2, 1d, 5); for (int item : gen1) { System.out.println("yield value: " + item); }
O gerador assíncrono permite criar uma sequência de valores de um determinado tipo, enquanto os valores são gerados de forma lenta e assíncrona.
async_generator<int> generate(int count) { for (int i = 0; i < count; i++) { co_await 1s; co_yield i; } }
Generator<Integer> gen1 = Coroutine.yieldAsync(5); Generator<Float> gen2 = Coroutine.yieldAsync(1f, 5); Generator<Double> gen3 = Coroutine.yieldAsync(v -> v * 2, 1d, 5); for (int item : gen1) { System.out.println("yield value: " + item); }
A tarefa executa o cálculo assíncrono, que é realizado preguiçosamente, enquanto a corotina não é executada até que a tarefa seja iniciada explicitamente.
As corotinas podem ser usadas como fluxos de luz. Nesse caso, o número de threads em execução no sistema pode ser limitado, por exemplo, não mais que 1000. E a corotina pode ser executada quantas vezes você quiser.
Ao iniciar uma corotina, é verificado se está pronta. Caso contrário, a rotina é pausada e o sistema operacional passa o manipulador para ele. Nesse ponto, um pedaço de código útil é executado. Quando a corotina está pronta, a renovação da corotina é realizada.
struct awaiter { bool await_ready() const { return false; } void await_resume() {} void await_suspend(std::coroutine_handle<> handler) { if (!handler.done()) { handler.resume(); } } }; co_await awaiter{};
Como ao iniciar um encadeamento, você pode passar Runnable ou Callable para uma corotina.
Coroutine.await(() -> { int sum = 5 + 10; }); Task<Integer> task = Coroutine.await(() -> { int sum = 5 + 10; return sum; });
O cronômetro pausa a tarefa atual pela duração necessária.
auto operator co_await(const std::chrono::system_clock::duration& duration) { return timer{duration}; } co_await 10ms;
Pode ser usado como um substituto para Thread.sleep ().
Coroutine.await(10, TimeUnit.MILLISECONDS);
As corotinas também podem ser usadas para escrever código sem bloqueio para trabalhar com o sistema de arquivos, a rede etc.
Como você pode ver, as corotinas facilitam a escrita de código assíncrono, permitindo que partes do código sejam executadas sem bloquear o fluxo.
As corotinas que planejam iniciar no C ++ 20 aparecerão como recursos de linguagem pura.
Geradores, tarefas e outras corotinas estão planejadas para serem adicionadas ao padrão C ++ 23 ou posterior.
Você mesmo pode escrever suas próprias rotinas ou usar uma biblioteca pronta, por exemplo,
cppcoro .
Os compiladores MVSC, Clang já suportam corotinas como uma extensão e o GCC está apenas no estágio de desenvolvimento.
O código fonte completo pode ser visualizado no github:
code