Viele moderne Sprachen unterstützen die Arbeit mit Coroutinen auf Sprachebene. Java unterstützt derzeit keine Coroutinen, aber es besteht die Hoffnung, dass sich die Dinge in Zukunft ändern können.
In C ++ 20 ist geplant, Unterstützung für die Arbeit mit Coroutinen einzuführen.
Mit JNI können wir Coroutinen in C ++ schreiben und in Java-Code verwenden.
Lassen Sie uns überlegen, welche nativen Coroutinen geschrieben werden können und wie sie in Java-Code verwendet werden.
Mit dem Generator können Sie eine Folge von Werten eines bestimmten Typs erstellen, während die Werte träge und synchron generiert werden.
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); }
Mit dem asynchronen Generator können Sie eine Folge von Werten eines bestimmten Typs erstellen, während die Werte träge und asynchron generiert werden.
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); }
Die Task führt eine asynchrone Berechnung durch, die träge ausgeführt wird, während die Coroutine erst ausgeführt wird, wenn die Task explizit gestartet wird.
Coroutinen können als Lichtströme verwendet werden. In diesem Fall kann die Anzahl der laufenden Threads im System begrenzt werden, z. B. nicht mehr als 1000. Und Coroutine kann beliebig oft ausgeführt werden.
Beim Starten einer Coroutine wird geprüft, ob sie bereit ist. Wenn nicht, wird die Coroutine angehalten und das Betriebssystem leitet den Handler an ihn weiter. Zu diesem Zeitpunkt wird ein nützlicher Code ausgeführt. Wenn die Coroutine fertig ist, wird die Coroutine erneuert.
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{};
Wie beim Starten eines Threads können Sie Runnable oder Callable an eine Coroutine übergeben.
Coroutine.await(() -> { int sum = 5 + 10; }); Task<Integer> task = Coroutine.await(() -> { int sum = 5 + 10; return sum; });
Der Timer hält die aktuelle Aufgabe für die erforderliche Dauer an.
auto operator co_await(const std::chrono::system_clock::duration& duration) { return timer{duration}; } co_await 10ms;
Kann als Ersatz für Thread.sleep () verwendet werden.
Coroutine.await(10, TimeUnit.MILLISECONDS);
Coroutinen können auch verwendet werden, um nicht blockierenden Code für die Arbeit mit dem Dateisystem, dem Netzwerk usw. zu schreiben.
Wie Sie sehen können, erleichtern Coroutinen das Schreiben von asynchronem Code, sodass Teile des Codes ausgeführt werden können, ohne den Stream zu blockieren.
Die Coroutinen, die in C ++ 20 gestartet werden sollen, werden als reine Sprachfunktionen angezeigt.
Generatoren, Tasks und andere Coroutinen sollen dem C ++ 23-Standard oder höher hinzugefügt werden.
Sie können Ihre eigenen Coroutinen selbst schreiben oder eine vorgefertigte Bibliothek verwenden, z. B.
cppcoro .
Die Compiler MVSC, Clang unterstützen Coroutinen bereits als Erweiterung, und GCC befindet sich erst in der Entwicklungsphase.
Der vollständige Quellcode kann auf github:
code eingesehen
werden