Frage

Ich bezweifle, kann es portabel gemacht werden, aber gibt es Lösungen gibt? Ich denke, es durch die Schaffung eines alternativen Stapel und Reseting SP, BP und IP auf Funktion Eintrag getan werden könnte, und mit Ertrag speichern IP und wiederherstellen SP + BP. Destruktoren und Ausnahme Sicherheit scheint schwierig, aber lösbar.

Ist es geschehen? Ist es unmöglich?

War es hilfreich?

Lösung

Ja, es kann getan werden, , ohne ein Problem. Alles was Sie brauchen ist ein wenig Assembler-Code den Call-Stack auf einen neu zugeordneten Stapel auf dem Heap zu bewegen.

Ich würde sehen Sie die boost :: Koroutine Bibliothek .

Das einzige, was Sie achten sollten für einen Stack-Überlauf. Auf den meisten Betriebssystemen den Stapel überfüllt wird eine segfault verursachen, da virtuelle Speicherseite nicht abgebildet wird. Allerdings, wenn Sie den Stapel auf dem Heap reservieren Sie erhalten keine Garantie. Sie daran, dass Sie nur daran.

Andere Tipps

Auf POSIX können Sie makecontext () / swapcontext () Routinen portably wechseln Kontexten Ausführung verwenden. Unter Windows können Sie den Faser-API verwenden. Ansonsten alles, was Sie brauchen, ist ein bisschen Leimaggregat Code, der die Maschine Kontextwechsel. Ich habe implementiert Koroutinen sowohl mit ASM (für AMD64) und mit swapcontext (); weder ist sehr hart.

Für die Nachwelt

Dmitry Vyukov hat einen cleveren Trick ucontext und setjump simulierten Koroutinen in C ++.

Auch Oliver Kowalke Kontext Bibliothek war vor kurzem angenommen in steigern, so hoffentlich werden wir eine aktualisierte Version von boost.coroutine sehen werden, die bald auf x86_64 funktioniert.

Es gibt keine einfache Möglichkeit, Koroutine zu implementieren. Weil Koroutine selbst ist aus C / C ++ 's Stapel Abstraktion wie Gewinde. Es kann also nicht ohne Sprachniveau Änderungen unterstützt zu unterstützen.

Zur Zeit (C ++ 11), werden alle vorhandenen C ++ Koroutine Implementierungen sind alle auf Baugruppenebene Hacking basiert, die einen sicheren und zuverlässigen Übergang über Plattformen zu hart ist. Um zuverlässig es seinen Standard muss und behandelt von Compilern, anstatt Hacking.

Es gibt ein Standardvorschlag - N3708 für diese. Überprüfen Sie es heraus, wenn Sie interessiert sind.

Das könnte Sie besser dran mit einem Iterator als ein Koroutine, wenn möglich. Auf diese Weise halten Sie können next() ruft den nächsten Wert zu bekommen, aber Sie können Ihren Zustand als Membervariablen anstelle von lokalen Variablen halten.

Es könnte die Dinge besser wartbar. Ein weiterer C ++ Entwickler möglicherweise nicht sofort die Koroutine verstehen, während sie mit einem Iterator besser vertraut sein könnten.

Für diejenigen, die wissen wollen, wie sie Koroutinen in C in einem tragbaren Weise nutzen kann ++ Sie müssen warten, für C + ̶ +17 ist das Warten vorbei (siehe unten)! Der Normenausschuss arbeitet an der Funktion finden Sie in der N3722 Papier . Um den aktuellen Entwurf des Papiers zusammenfassen, statt Async und Await, werden die Schlüsselwörter fortsetzbar und warten.

Werfen Sie einen Blick auf die experimentelle Implementierung in Visual Studio 2015 mit Microsofts experimentelle Umsetzung zu spielen. Es sieht nicht so aus wie Klirren eine Implementierung hat noch.

Es gibt eine gute Rede von Cppcon Koroutinen einem negativer Kopf Abstraktion die Vorteile der Verwendung Koroutinen umreißen in C ++ und wie wirkt er sich Einfachheit und Leistung des Codes.

Zur Zeit haben wir noch Bibliothek Implementierungen verwenden, aber in naher Zukunft werden wir Koroutinen als Kern C ++ Funktion.

Update: Sieht aus wie die Koroutine Implementierung für C ++ 20 ist geplant, wurde aber als technische Spezifikation mit C ++ 17 ( p0057r2 ). Visual C ++, Klirren und gcc können Sie bei der Verwendung eines Kompilierung-Flag entscheiden.

COROUTINE eine portable C ++ Bibliothek für Koroutine Sequenzierung zeigen in die richtige Richtung? Es scheint wie eine elegante Lösung, die den Test der Zeit gedauert hat ..... es ist 9 Jahre alt!

Im DOC-Ordner ist ein pdf des Papiers A Tragbare C ++ Bibliothek für Coroutine Sequenzierung von Keld Helsgaun, die die Bibliothek beschreibt und kurze Beispiele stellt es zu benutzen.

[Update] Ich mache tatsächlich erfolgreiche Anwendung es selbst. Neugier erwischte die bessere von mir, so ich sah in diese Lösung und fand es eine gute Passform für ein Problem war, ich habe seit einiger Zeit arbeiten!

Ich denke nicht, es gibt viele ausgewachsene, saubere Implementierungen in C ++. Ein Versuch, die Ich mag Adam Dunkels' Protothread-Bibliothek .

Siehe auch Protothread: ereignisgesteuerte Programmierung von Speicherbeschränkte Embedded-Systemen zu vereinfachen in der ACM Digital Library und Diskussion in Wikipedia Thema Protothread ,

Eine neue Bibliothek, -Boost .Context , wurde heute für die Umsetzung Koroutinen mit tragbaren Funktionen freigegeben.

Dies ist ein alter Thread, aber ich mag einen Hack Duff Gerät zu legen nahe, dass nicht o abhängig (soweit ich mich erinnere):

C Koroutinen mit Duff Gerät

Und als Beispiel, hier ist eine Telnet-Bibliothek, die ich geändert Koroutinen statt Gabel / Threads zu verwenden: Bibliothek Telnet cli mit Koroutinen

Und da Standard C bis C99 vor im Wesentlichen eine echte Teilmenge von C ++ ist, das funktioniert gut in C ++ zu.

Es basiert auf (cringe) Makros, aber die folgende Website bietet eine einfach zu bedienende Generator Implementierung: http://www.codeproject.com/KB/cpp/cpp_generators.aspx

Ich habe mit einer Implementierung kommen ohne asm Code. Die Idee ist, das System des Gewindeerzeugungsfunktion zu verwenden Stapel und Kontext zu initialisieren, und verwenden setjmp / longjmp Kontext zu wechseln. Aber es ist nicht tragbar, finden Sie in der rel="nofollow"> wenn Sie interessiert sind.

https://github.com/tonbit/coroutine ist C ++ 11 Einzel .h asymmetrisches Koroutine Implementierung unterstützen RESUME / Ausbeute / erwarten Primitiven und Kanalmodell. Es Implementierung über ucontext / Faser, nicht abhängig von Auftrieb, läuft auf Linux / Windows / macOS. Es ist ein guter Ausgangspunkt Umsetzung Koroutine in c ++ zu lernen.

meine Implementierung Check out, es zeigt den asm Hacking Punkt und ist einfach:

https://github.com/user1095108/generic/blob/master /coroutine.hpp

Sie sollten immer prüfen Fäden statt verwendet; vor allem in der modernen Hardware. Wenn Sie Arbeit haben, die logisch in Co-Routinen getrennt werden können, Threads bedeutet, die Arbeit könnte in der Tat gleichzeitig durchgeführt werden, durch getrennte Ausführungseinheiten (Prozessorkerne).

Aber vielleicht wollen Sie Koroutinen verwenden, vielleicht, weil Sie einen gut getesteten Algorithmus haben, die bereits geschrieben wurde und getestet, dass die Art und Weise, oder weil Sie Code portieren, dass die Art und Weise geschrieben.

Wenn Sie unter Windows arbeiten, sollten Sie einen Blick auf Fasern . Fasern geben Ihnen einen Koroutine artigen Rahmen mit Unterstützung der OS.

Ich bin nicht vertraut mit anderen OS Alternativen es empfehlen.

WvCont ist ein Teil der WvStreams , die sogenannte implementiert halb Koroutinen . Diese sind ein wenig leichter zu handhaben als Voll auf Koroutinen. Sie in es nennen, und es ergibt sich wieder an die Person, die es genannt

Es implementiert ist unter Verwendung des flexibleren WvTask, die voll-auf Koroutinen unterstützt; Sie können es in derselben Bibliothek finden.

Arbeiten auf win32 und Linux, zumindest, und wahrscheinlich jedem anderen Unix-System.

Ich habe versucht, Koroutinen mich mit C ++ 11 und Threads zu implementieren:

#include <iostream>
#include <thread>

class InterruptedException : public std::exception {
};

class AsyncThread {
public:
    AsyncThread() {
        std::unique_lock<std::mutex> lock(mutex);
        thread.reset(new std::thread(std::bind(&AsyncThread::run, this)));
        conditionVar.wait(lock); // wait for the thread to start
    }
    ~AsyncThread() {
        {
            std::lock_guard<std::mutex> _(mutex);
            quit = true;
        }
        conditionVar.notify_all();
        thread->join();
    }
    void run() {
        try {
            yield();
            for (int i = 0; i < 7; ++i) {
                std::cout << i << std::endl;
                yield();
            }
        } catch (InterruptedException& e) {
            return;
        }
        std::lock_guard<std::mutex> lock(mutex);
        quit = true;
        conditionVar.notify_all();
    }
    void yield() {
        std::unique_lock<std::mutex> lock(mutex);
        conditionVar.notify_all();
        conditionVar.wait(lock);
        if (quit) {
            throw InterruptedException();
        }
    }
    void step() {
        std::unique_lock<std::mutex> lock(mutex);
        if (!quit) {
            conditionVar.notify_all();
            conditionVar.wait(lock);
        }
    }
private:
    std::unique_ptr<std::thread> thread;
    std::condition_variable conditionVar;
    std::mutex mutex;
    bool quit = false;
};

int main() {
    AsyncThread asyncThread;
    for (int i = 0; i < 3; ++i) {
        std::cout << "main: " << i << std::endl;
        asyncThread.step();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top