Heim >Backend-Entwicklung >C++ >Detaillierte Erläuterung der Coroutine-Programmierung in C++

Detaillierte Erläuterung der Coroutine-Programmierung in C++

WBOY
WBOYOriginal
2023-08-22 12:18:251227Durchsuche

Detaillierte Erläuterung der Coroutine-Programmierung in C++

Mit der kontinuierlichen Weiterentwicklung der Computertechnologie werden auch die Programmiermethoden ständig innoviert und verbessert. Unter ihnen gilt die Coroutinen-Programmierung als relativ neue Programmiermethode. Die Coroutine-Programmierung wurde erstmals 1958 von Melvin Conway in seiner Arbeit vorgeschlagen. Aber es ist die Sprache C++, die die Coroutine-Programmierung wirklich fördert und anwendet. Daher wird in diesem Artikel die Coroutine-Programmierung aus der Perspektive der C++-Sprache ausführlich analysiert und erläutert.

Was ist eine Coroutine?

Bevor wir die Coroutine-Programmierung erklären, müssen wir zunächst verstehen, was Coroutine ist. Coroutinen können einfach als spezielle Unterfunktionen verstanden werden, die angehalten werden können, wenn die Ausführung einen bestimmten Punkt erreicht, und auf das erneute Erwachen warten, bevor sie mit der Ausführung fortfahren. Im Vergleich zu herkömmlichen Funktionsaufrufen ist der Ausführungsmodus von Coroutinen flexibler.

Das Anhalten und Aufwecken der Coroutine kann von ihr selbst gesteuert werden, nicht vom Anrufer. Dies hat den Vorteil, dass die Coroutine, wenn sie einige Langzeitoperationen ausführt, CPU-Ressourcen aufgeben und andere Aufgaben ausführen lassen kann, wodurch die Computerressourcen besser genutzt werden.

In C++ können Coroutinen mithilfe des Schlüsselworts co_await implementiert werden, das es einer Coroutine ermöglicht, anzuhalten, wenn die Ausführung einen bestimmten Punkt erreicht, und nach Erreichen voreingestellter Bedingungen wieder zu aktivieren.

Wie verwendet man Coroutinen?

In C++ erfordert die Verwendung von Coroutinen die Hilfe einer Coroutine-Bibliothek. Derzeit sind Boost.Coroutine und die mit C++20 gelieferte Coroutine-Bibliothek die am häufigsten verwendeten. Nehmen wir Coroutinen in C++20 als Beispiel, um die Verwendung von Coroutinen zu erklären.

  1. Coroutine-Funktionen definieren

In C++20 können wir die Schlüsselwörter co_await und co_yield verwenden, um Coroutine-Funktionen zu definieren. co_await bedeutet, die aktuelle Coroutine anzuhalten und auf das Erwachen zu warten, während co_yield bedeutet, die aktuelle Coroutine anzuhalten und einige Werte oder Status zurückzugeben, wenn die Coroutine-Funktion einen bestimmten Punkt erreicht. Das Folgende ist ein einfaches Beispiel einer Coroutine-Funktion:

#include <iostream>
#include <coroutine>
using namespace std;
 
struct HelloWorld {
    struct promise_type {
        HelloWorld get_return_object() {
            return {};
        }
        std::suspend_never initial_suspend() {
            return {};
        }
        std::suspend_never final_suspend() noexcept {
            return {};
        }
        void unhandled_exception() {}
    };
    
    HelloWorld() {};
    void print() {
        cout << "Hello, world!" << endl;
    }
 
    void operator()() {}
};
 
int main() {
    HelloWorld hello_world;
    hello_world();
    hello_world.print();
    return 0;
}

Im obigen Beispiel definieren wir eine Struktur namens HelloWorld, bei der es sich um eine Coroutine-Funktion handelt. In dieser Struktur implementieren wir eine verschachtelte Struktur namens Promise_Type, die das Verhalten der Coroutine-Funktion steuert. Wir definieren auch eine Mitgliedsfunktion namens print, die die Zeichenfolge „Hello, world!“ ausgibt.

  1. Koroutinenfunktion aufrufen

In C++20 können wir die Klasse coroutine_handle verwenden, um den Ausführungsstatus der Koroutine zu steuern. Bevor wir die Coroutine-Funktion aufrufen, müssen wir ein coroutine_handle-Objekt erhalten. Nachdem die Coroutine-Funktion ausgeführt wurde, müssen wir das Objekt manuell freigeben. Das Beispiel lautet wie folgt:

int main() {
    HelloWorld hello_world;
    auto handle = hello_world();
    handle.resume();
    hello_world.print();
    handle.destroy();
    return 0;
}

Im obigen Beispiel erhalten wir zuerst ein coroutine_handle-Objekt und rufen dann seine Funktion resume() auf, die den Code in der Coroutine-Funktion ausführt, bis das Schlüsselwort co_await oder co_yield angetroffen wird aktuelle Coroutine. Schließlich rufen wir manuell die Funktion destroy() auf, um die Coroutine freizugeben.

  1. Verwenden Sie co_await und co_yield in der Coroutine-Funktion.

In der Coroutine-Funktion können wir die Coroutine über die Schlüsselwörter co_await und co_yield anhalten. Hier ist ein Beispiel:

#include <iostream>
#include <coroutine>
using namespace std;
 
struct Generator {
    struct promise_type {
        int current_value;
        std::suspend_always yield_value(int value) {
            current_value = value;
            return {};
        }
        std::suspend_never initial_suspend() {
            return {};
        }
        std::suspend_never final_suspend() noexcept {
            return {};
        }
        Generator get_return_object() {
            return Generator(coroutine_handle<promise_type>::from_promise(*this));
        }
        void unhandled_exception() {}
    };
    
    Generator(coroutine_handle<promise_type> h) : coro(h) {}
    coroutine_handle<promise_type> coro;
    
    bool next() {
        coro.resume();
        return not coro.done();
    }
 
    int value() {
        return coro.promise().current_value;
    }
 
    ~Generator() {
        coro.destroy();
    }
};
 
Generator fibonacci(int to) {
    int a = 0, b = 1;
    while (a <= to) {
        co_yield a;
        auto tmp = a + b;
        a = b;
        b = tmp;
    }
}
 
int main() {
    Generator gen = fibonacci(10);
    while (gen.next()) {
        cout << gen.value() << " ";
    }
    return 0;
}

Im obigen Beispiel haben wir eine Struktur namens Generator definiert, die auch eine Coroutine-Funktion ist. Wir definieren eine While-Schleife in der Coroutine-Funktion. Bei jeder Ausführung des Schlüsselworts co_yield wird der aktuelle a-Wert an den Aufrufer zurückgegeben und die Werte von a und b aktualisiert. In der Hauptfunktion erhalten wir ein Generator-Objekt, indem wir die Generator-Funktion aufrufen und dann kontinuierlich deren next()-Funktion aufrufen, um das von der Coroutine-Funktion zurückgegebene Ergebnis zu erhalten.

Zusammenfassung

Anhand der obigen Beispiele können wir sehen, dass die Coroutine-Programmierung das Programm effizienter und flexibler machen kann. Im wirklichen Leben wird die Coroutine-Programmierung häufig in verschiedenen gleichzeitigen Programmierszenarien verwendet, wie z. B. Netzwerkprogrammierung, Multithread-Programmierung usw.

In C++ können wir mit Hilfe der Coroutine-Bibliothek die Coroutine-Programmierung einfacher und effizienter implementieren. Mit der Entwicklung der Computertechnologie und der kontinuierlichen Verbesserung des C++-Standards wird die Coroutine-Programmierung in Zukunft in mehr Situationen angewendet und gefördert.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Coroutine-Programmierung in C++. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn