Frage

Ich arbeite von Bjarne Stroustrup in der Programmiersprache C ++ einige der Übungen durch. Ich bin von Problem 11 am Ende des Kapitels verwechselt 12:

(* 5) Design und eine Bibliothek implementieren ereignisgesteuerte Simulationen für das Schreiben. Hinweis: . ... Ein Objekt der Klasse Aufgabe sollte in der Lage sein, seinen Zustand zu speichern und dieser Zustand wieder hergestellt haben, so dass es als Koroutine arbeiten kann. Besondere Aufgaben können als Objekte der Klassen von Aufgabe abgeleitet definiert werden. Das Programm wird von einer Task ausgeführt werden kann als virtuelle Funktion definiert werden. ... Es sollte ein Scheduler die Implementierung eines Konzepts der virtuellen Zeit. ... Die Aufgaben müssen kommunizieren. Entwerfen Sie eine Klasse-Warteschlange für das. ...

Ich bin nicht sicher, was genau das ist zu fragen. Ist eine Aufgabe, ein separater Thread? (Soweit ich weiß, es ist nicht möglich, einen neuen Thread ohne Systemaufrufe zu erstellen, und da dies ein Buch über C ++ Ich glaube nicht, das ist die Absicht.) Ohne Unterbrechungen, wie ist es möglich, einen Betrieb zu starten und stoppen Funktion? Ich nehme an, dies beschäftigt Warte beinhalten würde (die ständig Schleife zu sagen ist und eine Bedingung überprüfen), obwohl ich kann nicht sehen, wie das auf eine Funktion angewandt werden könnte, die für einige Zeit nicht beenden konnte (wenn es eine unendliche Schleife, zum Beispiel enthält) .

EDIT:. Bitte lesen Sie meinen Beitrag unten mit mehr Informationen

War es hilfreich?

Lösung

  

. Hinweis:

ist ein Verweis auf eine alte kooperative Multi-Tasking-Bibliothek, die mit frühen Versionen von Cfront (Sie können auch auf dieser Seite herunterladen).

Wenn Sie lesen das Papier „ Eine Reihe von C ++ Klassen für Co-Routine Stil Programmierung “Dinge werden viel mehr Sinn machen.


Das Hinzufügen eines Bit:

Ich bin kein alt genug Programmierer haben die Task-Bibliothek verwendet. Aber ich weiß, dass C ++ entwickelt wurde, nachdem Stroustrup eine Simulation in Simula schrieb, dass viele der gleichen Eigenschaften wie die Task-Bibliothek hatte, also habe ich immer neugierig gewesen.

Wenn ich die Übung aus dem Buch zu implementieren wäre, würde ich wahrscheinlich so mache es (bitte beachten Sie, ich habe diesen Code nicht getestet oder sogar versucht, es zu kompilieren):

class Scheduler {
    std::list<*ITask> tasks;
  public:
    void run()
    {
        while (1) // or at least until some message is sent to stop running
            for (std::list<*ITask>::iterator itor = tasks.begin()
                      , std::list<*ITask>::iterator end = tasks.end()
                    ; itor != end
                    ; ++itor)
                (*itor)->run(); // yes, two dereferences
    }

    void add_task(ITask* task)
    {
        tasks.push_back(task);
    }
};

struct ITask {
    virtual ~ITask() { }
    virtual void run() = 0;
};

Ich kenne Leute, mit einigen meiner Entscheidungen nicht einverstanden ist. Zum Beispiel einer Struktur für die Schnittstelle; aber structs haben das Verhalten, das von ihnen erbt standardmäßig öffentlich ist (wo von Klassen erben standardmäßig privat ist), und ich sehe keinen Wert in vererben privat von einer Schnittstelle, also warum nicht öffentlicher Vererbung der Standards machen?

Die Idee ist, dass iTask ruft :: run () den Scheduler blockieren, bis die Aufgabe an einem Punkt ankommt, wo es unterbrochen werden kann, bei dem die Aufgabe Punkt aus der run-Methode zurück, und warten Sie, bis der Scheduler Anrufe laufen wieder fortzusetzen. Die „Genossenschaft“ in „kooperativem Multitasking“ bedeutet „Aufgaben sagen, wenn sie unterbrochen werden können“ ( „Koroutine“ bedeutet in der Regel „kooperatives Multitasking“). Eine einfache Aufgabe nur in der Methode run () eine Sache tun kann, eine komplexere Aufgabe, eine Zustandsmaschine implementieren kann, und kann seinen run () Methode verwenden, um herauszufinden, was der Objektzustand ist zur Zeit in und Anrufe zu anderen Methoden macht basierend auf diesem Zustand. Die Aufgaben muss abtreten Kontrolle ab und zu dafür zu arbeiten, denn das ist die Definition ist „kooperatives Multitasking.“ Es ist auch der Grund, warum alle modernen Betriebssysteme werden keine kooperatives Multitasking verwenden.

Diese Implementierung ist nicht (1) Messeplanung folgen (vielleicht ein Lauf insgesamt Uhr halten in Aufgabe des Lauf Zecken verbrachte in () -Methode, und das Überspringen Aufgaben, die zu viel Zeit relativ, bis die anderen Aufgaben zu den anderen verwendet haben „fangen up "), (2) ermöglichen Aufgaben entfernt werden, oder sogar (3) ermöglichen der Scheduler gestoppt werden.

Was zwischen den Aufgaben in Verbindung steht, können Sie erwägen, suchen Plan 9 des libtask oder Rob Pike Newsqueak für Inspiration (die "UNIX-Implementierung von Newsqueak" Download enthält ein Papier, "die Umsetzung der Newsqueak", die Message-Passing diskutiert in einer interessanten virtuellen Maschine).

Aber ich glaube, das ist das Grundgerüst Stroustrup im Sinne hatte.

Andere Tipps

Hier ist mein Verständnis einer „ereignisgesteuerten Simulation“:

  • A-Controller übernimmt eine Ereigniswarteschlange, Ereignisse der Planung zu bestimmten Zeiten auftreten, dann auf der Warteschlange Anfang Ereignis ausführt.
  • Veranstaltungen OCUR sofort zu dem geplanten Zeitpunkt. Um zum Beispiel die Position und den Zustand eines Unternehmens in der Simulation, so dass der Zustandsvektor ist gültig in der aktuellen Simulationszeit würde aktualisieren ein „move“ Ereignis. Ein „Gefühl“ Ereignis würde sicherstellen, dass alle Entitäten Staaten zum jetzigen Zeitpunkt sind, dann einige mathematischen Modelle verwenden, um zu bewerten, wie gut die aktuelle Einheit der anderen Einheiten erfassen kann. (Denken Sie Roboter bewegen auf einem Brett.)
  • So die Zeit voranschreitet diskontinuierlich, von Ereignis zu Ereignis zu springen. Vergleichen Sie dies mit einer zeitgesteuerten Simulation, in denen die Zeit bewegt sich in diskreten Schritten und alle Staaten Einheiten jeden Zeitschritt aktualisiert werden (a la meisten Simulink-Modelle).
  • Veranstaltungen können dann auf ihre natürliche Rate auftreten. Es ist in der Regel nicht sinnvoll, alle Daten am besten Preis in der Simulation neu zu berechnen.

Die meisten Produktionsereignisgesteuerte Simulationen in einem einzigen Thread. Sie können ihrem Wesen nach komplex sein, so versuchen, eine Multi-Threaded-Simulation zu synchronisieren neigt exponentielle Schichten Komplexität hinzuzufügen. Mit dieser sagte, gibt es einen Standard für Multi-Prozess-Militär-Simulationen genannt Verteiler- Interactive Simulation (DIS) dass verwendet vordefinierte TCP-Nachrichten-Daten zwischen den Prozessen zu übertragen.

EDIT: Es ist wichtig, einen Unterschied zwischen Modellierung und Simulation zu definieren. Ein Modell ist eine mathematische Darstellung eines Systems oder Prozesses. Eine Simulation wird von einem oder mehreren Modellen gebaut, die über eine Zeitperiode ausgeführt werden. Wieder hüpft eine ereignisgesteuerte Simulation von Ereignisse zu Ereignisse, während eine Zeitsimulation läuft bei einem konstanten Zeitschritt angetrieben wird.

Klingt für mich wie die Übung, die Sie fragt, einen kooperativen Multi-Tasking-Scheduler zu implementieren. Der Scheduler arbeitet in virtueller Zeit (Zeit-Ticks Sie definieren / Arbeitsgeräte auf welcher Ebene auch immer Sie wollen), wählt eine Aufgabe zugrunde, laufen in der Warteschlange (beachten Sie, dass die Beschreibung erwähnt Sie ein zu implementieren brauchen würde), und wenn die aktuelle Aufgabe ist getan, wählt der Scheduler die nächsten und startet es ausgeführt wird.

Die verallgemeinerte Struktur einer diskreten Ereignissimulation auf einer Prioritätswarteschlange auf einem Zeitwert verkeilt basiert. Auf breiter Ebene geht es so:

    While (not end condition):
        Pop next event (one with the lowest time) from the priority queue
        Process that event, which may generate more events
        If a new event is generated:
            Place this on the priority queue keyed at its generated time

Co-Routinen ändern, um die Ansicht des Modells davon, dass ereigniszentrierte zu seinem entity-centric. Entitäten können einige Lebenszyklus durchlaufen (beispielsweise anzunehmen, Schnappen Ressource X, Prozess Job, Trenn Ressource X, place Job in der Warteschlange für den nächsten Schritt). Dies ist etwas einfacher zu programmieren als die Greifer Ressourcen mit Semaphore-like Synchronisierungsgrund behandelt werden. Die Aufträge und die Synchronisation Primitiven erzeugen, um die Ereignisse und sie hinter den Kulissen Warteschlange.

Das gibt ein Modell konzeptionell ähnlich wie Prozesse in einem Betriebssystem und ein Planer Wach den Prozess, wenn sein Eingang oder eine gemeinsam genutzte Ressource sie angefordert hat, zur Verfügung steht. Die Co-Routine Modell macht die Simulation ziemlich viel einfacher zu verstehen, die für die Simulation komplexer Systeme nützlich ist.

(Ich bin kein C ++ dev)

Wahrscheinlich, was es bedeutet, dass Sie eine Klasse-Aufgabe (wie in dem Ereignisse) erstellen müssen, die meist aus einem Callback-Funktion Zeiger und eine geplanten Zeit bestehen wird, und können in einer Liste in der Scheduler-Klasse gespeichert werden, was wiederum grundsätzlich sollte Spur eines Zeitzählers halten und Funktion jeder einzelnen Aufgabe aufrufen, wenn die Zeit kommt. Diese Aufgaben sollten von den Aufgaben der Simulation erstellt werden.

Wenn Sie Hilfe auf der diskreten Simulation Seite benötigen, gehen Sie vor und die Frage bearbeiten.

Dies ist als Reaktion auf titaniumdecoy Kommentar zu SottieT812 Antwort. Es ist viel zu groß für einen Kommentar, so habe ich beschlossen, es eine andere Antwort zu machen.

Es ist Ereignis im Sinne angetrieben, dass die Simulation Zustand nur Änderungen in Reaktion auf ein Ereignis. Zum Beispiel wird angenommen, dass Sie zwei Ereignisse haben Raketenstart und Rakete Auswirkungen . Wenn der Start Ereignis ausgeführt wird, rechnet sie aus, wann und wo es auswirken wird, und plant eine Auswirkungen Ereignis für die entsprechende Zeit. Die Position der Rakete nicht zwischen dem Start und den Auswirkungen berechnet, obwohl es wird wahrscheinlich eine Methode, die von anderen Objekten aufgerufen werden kann, um die Position zu einem bestimmten Zeitpunkt zu erhalten.

Dies ist im Gegensatz zu einer zeitgesteuerten Simulation, wobei die genaue Position der Rakete (und jedes anderes Objekt in der Simulation) nach jedem Zeitschritt berechnet werden, sagen 1 Sekunde.

Abhängig von den Eigenschaften des Modells, die Treue der Antwort erforderlich, und viele andere Faktoren, entweder ereignisgesteuert oder zeitgesteuerten Simulation kann eine bessere Leistung.

Edit: Wenn jemand mehr in dem Lernen interessiert, einen Blick auf die Papiere aus der Winter-Simulationskonferenz

Es gibt ein Buch und Rahmen genannt DEMOS (Discrete Event Modelling auf Simula), die eine Co-Routine basierend Rahmen beschreibt (die namensgebende DEMOS). Trotz 30 Jahre sein oder so alt DEMOS ist eigentlich ein ganz schönes System und Graham Birtwistle ist ein wirklich netter Kerl.

Wenn Sie Co-Routinen auf C ++ (man denke setjump / Weitsprung) implementieren, sollten Sie für eine Beschreibung eines an diesem Buch einen Blick wirklich, wirklich elegant Binärereignis Modellierungsrahmen. Obwohl es 30 Jahre alt ist, ist es ein bisschen wie ein zu eng, und hat immer noch eine Fangemeinde.

In dem Papier verbunden durch "me.yahoo.com / ...", die die task.h Klasse beschreibt:

  1. Aufgaben ausführen parallel
  2. Eine Aufgabe ausgesetzt werden kann und später wieder aufgenommen

Die Bibliothek wird als Methode der Multi beschrieben.

Ist es möglich, dies zu tun, ohne Gewinde oder separate Prozesse verwenden?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top