================== Promises & Futures ================== Die spontan entwickelte `JobStatus`-Klasse könnte natürlich erweitert werden und beispielsweise auch dazu dienen, ein Resultat zu übermitteln. Glücklicherweise gibt es bereits eine entsprechende Klasse in der Standardbibliothek von C++11. Relevant sind hier die Klassen `std::promise` und `std::future`, beide aus ``. Ein `std::promise`-Objekt ähnelt unserem `JobStatus` -- nur gibt es nur eine Funktion `set_value` zum Setzen des zurückzugebenden Werts. Statt der Methode `wait` gibt es die Möglichkeit, mit `get_future` genau einmal ein `std::future`-Objekt abzurufen, das wiederum die Methode `get` anbietet, die die Synchronisierung einschließt. Die Funktionalität von `JobStatus` wurde somit in zwei Klassen bzw. zwei Objekte augesplittet: * std::promise ist für den Auftragnehmer (also beispielsweise ein Worker in unserem Thread-Pool). * std::future ist für den Auftraggeber. Durch die Aufsplittung kann nicht versehentlich der Auftraggeber so tun, als ob der Auftrag bereits erledigt wäre. Wer nur ein `std::future`-Objekt hat, kommt nicht mehr an das `std::promise`-Objekt heran. Umgekehrt gilt, dass wenn einmal mit `get_future` ein `std::future`-Objekt vom `std::promise`-Objekt erzeugt wurde, dann klappt dies nicht ein zweites Mal. So könnte ein Trivial-Beispiel aussehen: ---- CODE (type=cpp) ---------------------------------------------------------- int main() { ThreadPool pool(2); std::promise promise; std::future future = promise.get_future(); pool.submit([&]() { printf("Hello!\n"); promise.set_value(42); }); printf("Job returned %d\n", future.get()); } ------------------------------------------------------------------------------- Eine Kombination aus `std::promise` und `std::function` steht mit `std::packaged_task` zur Verfügung, so dass der Thread-Pool von `std::function` auf `std::packaged_task` umgestellt werden kann. Dann liefert `submit` immer ein `std::future`-Objekt zurück und somit ist eine Synchronisierung immer möglich: :import:session16/tpool6.cpp Hinweis: Ältere g++-Versionen kommen damit nicht zurecht (siehe `https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53137`). Dies betrifft leider momentan noch die Maschinen im E.44. Probieren Sie dies auf der Thales aus oder ersetzen Sie den Aufruf `process_jobs();` durch `this->process_jobs()`. Der gleiche Hinweis gilt auch für die Beispiele auf den folgenden Seiten. Aufgabe ======= Passen Sie Ihre zuvor entwickelte Version zur Matrix-Initialisierung an den neuen Thread-Pool an. Die Lösungen können wieder auf der Thales eingereicht werden: ---- CODE (type=sh) ----------------------------------------------------------- submit hpc session16 session16.tar ------------------------------------------------------------------------------- :navigate: up -> doc:index back -> doc:session16/page06