Softwareentwicklung: C++20-Coroutinen effizient verwenden, Teil 1

Coroutinen sind ein mächtiges Feature in C++. Sie erlauben, asynchronen, nicht blockierenden Code zu schreiben.

Artikel verschenken
vorlesen Druckansicht
Lesezeit: 11 Min.
Von
  • Andreas Fertig
Inhaltsverzeichnis

Coroutinen findet man im Sprachstandard seit C++20. In der Informatik sind sie nichts Neues, der Begriff wurde erstmals 1958 von Melvin Conway geprägt. Um Coroutinen zu verstehen, ist es hilfreich, den Unterschied zwischen Funktionen und Coroutinen zu kennen. Beim Aufruf der Unterfunktion wird die Funktion unterbrochen, bis die Unterfunktion zurückkehrt. Jeder neue Aufruf der Unterfunktion beginnt bei null. Wer einen Zustand erhalten will, muss ihn über Parameter an die Unterfunktion übergeben.

Anders ist der Kontrollfluss bei einer Coroutine. Ein Aufrufer ruft eine Coroutine als Unterfunktion auf. Sie hat die Fähigkeit, sich zu unterbrechen und die Kontrolle an die aufrufende Funktion zurückzugeben. Das Abgeben der Kontrolle gelingt durch eines der drei neuen Schlüsselwörter in C++20: co_yield, co_await oder co_return. Bei co_return ist die Coroutine wie eine gewöhnliche Funktion beendet. Die beiden anderen Varianten ermöglichen es, die Kontrolle abzugeben und die Coroutine in dem Zustand wieder aufzunehmen, in dem sie verlassen wurde. Der Vorteil einer Coroutine ist also, dass sie sich pausieren und fortsetzen lässt. Die aufrufende Funktion bestimmt, ob eine Coroutine fortgesetzt wird oder ob das aktuelle Resultat bereits das gewünschte ist.

iX-tract
  • Die in C++20 eingefĂĽhrten Coroutinen sind eine bedeutende Erweiterung des Sprachstandards; sie ermöglichen es, asynchrone und nicht blockierende Operationen einfach zu implementieren.
  • Coroutinen können die AusfĂĽhrung unterbrechen und später wieder fortsetzen.
  • Die SchlĂĽsselwörter co_yield und co_await ermöglichen es, Werte aus einer Coroutine zu erzeugen, ohne diese nach jeder Produktion zu beenden.

Gewöhnliche Funktionen sind ein Spezialfall einer Coroutine, die lediglich co_return nutzt und nicht co_yield oder co_await. Die Coroutine wendet einen simplen Trick an, um den Zustand zu speichern. Alle lokalen Daten und Parameter werden auf einem Heap-allozierten Speicher abgelegt. Jede Coroutine erstellt diesen Coroutinen-Frame beim erstmaligen Aufruf. Eine mehrfach gestartete Coroutine legt pro Start einen Frame an, der am Ende der Lebenszeit zerstört wird. Andere Programmiersprachen haben eine andere Implementierung: Dort speichern Coroutinen ihren Zustand in einem speziellen Stackbereich. Diese Form der Implementierung wurde für C++ diskutiert, aber letztlich verworfen. Das folgende Listing zeigt die Verwendung von co_yield und co_await; der vollständige Ablauf ist im Abschnitt "Die Beispiel-Coroutine Chat" beschrieben.

Das war die Leseprobe unseres heise-Plus-Artikels "Softwareentwicklung: C++20-Coroutinen effizient verwenden, Teil 1". Mit einem heise-Plus-Abo können Sie den ganzen Artikel lesen.