Open Source im professionellen Einsatz
Linux-Magazin 05/2010
794

Asynchron

Relativ spät fanden die asynchronen Funktionsaufrufe Eingang in C++0x. Sie gestatten es auf elegante Art, einen Job in einem neuen Thread zu starten und das Ergebnis später abzuholen. Das Objekt, das den Wert produziert, wird Promise, das Objekt, das den Wert einfordert, Future genannt. Das Programmschnipsel in Listing 5 verdeutlicht den Zusammenhang.

Die Funktion »asyncFun«, die über »std::promise<int>« parametrisiert wird, setzt das Ergebnis, das auch eine Exception sein kann. Der Thread in Zeile 13 startet die Funktion. Das Future verbindet sich mit dem Promise durch den Aufruf »intPromise.get_future« und holt sich durch »intFuture.get()« das Ergebnis der Funktion. Wenn das Promise seinen Wert noch nicht berechnet hat, blockiert dieser Aufruf.

Mit »std::async« [7] bietet C++0x - aller Voraussicht nach - eine einfache Schnittstelle für den Umgang mit asynchronen Funktionsaufrufen.

Listing 4: Einmaliges
Initialisieren von Daten

01 class MyClass{
02   int i;
03 public:
04   MyClass(int i_):i(i_){}
05 };
06 std::once_flag flag;
07 
08 void createInstance(){
09         p=new MyClass(17);
10 }
11 
12 void bar(){
13   std::call_once(flag,createInstance);
14 }

Listing 5: Promise und
Future

01 void asyncFun(std::promise<int> intPromise){
02   int result;
03   try {
04     // calculate the result
05     intPromise.set_value(result);
06   } catch (MyException e) {
07     intPromise.set_exception(std::copy_exception(e));
08   }
09 }
10 
11 std::promise<int> intPromise;
12 std::unique_future<int> intFuture = intPromise.get_future();
13 std::thread t(asyncFun, std::move(intPromise));
14 // do some other stuff
15 int result = intFuture.get(); // may throw MyException

Reguläre Ausdrücke

Wie die neue Threading-Funktionalität in C++0x aus anderen Programmiersprachen schon bekannt ist, so auch die regulären Ausdrücke. Sie sind das Mittel der Wahl, um Text effizient zu verarbeiten, und doch waren sie in der Standardbibliothek von C++ bisher nicht verfügbar. Die meisten C++-Entwickler haben sich mit einer String-Toolsammlung beholfen.

Der Umgang mit regulären Ausdrücken in C++0x lässt sich in drei Schritte (Listing 6) zerlegen:

  • »std::regex rgx« enthält den regulären
    Ausdruck
  • »std::smatch match« erhält das Ergebnis der
    Suche
  • »std::regex_search« verarbeitet das Suchergebnis
    weiter

Der Ausdruck »std::regex rgx(R"d+")« verwendet die mit C++0x neuen so genannten Raw-String-Literale. »d« steht dabei in regulären Ausdrücken für eine Ziffer. Dementsprechend steht der Ausdruck »d+« für ein Wort, das mindestens eine Ziffer enthält.

Der String folgt standardmäßig der ECMA-Skriptgrammatik, es lassen sich aber auch andere Grammatiken verwenden. »std::smatch match« erhält das Ergebnis der Suche und bietet ein reiches Interface an: Es lässt sich unter anderem nach dem Gesamttreffer, dessen Position, seinem Suffix oder Präfix, seiner Länge oder auch Teiltreffern in dem zu analysierenden String fragen. Neben »std::regex_search«, das den ersten Treffer »std::string("123A43")« sucht, verlangt »std::regex_match« einen genauen Treffer und gibt ein Boolean zurück. »std::regex_replace« hingegen ersetzt den Treffer mit einem neuen String.

Die neue Bibliotheksfunktionalität erlaubt außerdem das wiederholte Suchen mit Hilfe von regulären Ausdrücken (Listing 7). Der Code »std::sregex_iterator it1(str1.begin(),str1.end(),reg1)« erzeugt einen Iterator, der über alle Zeichen aus »std::string str1="1,2,3,4,5,6,7,8,9,10,11,12"« iteriert und nur die Zeichen zurückgibt, die nicht in dem regulären Ausdruck »std::regex reg1("[^13579,]"« enthalten sind. Dies sind genau die geraden Zahlen.

Abbildung 1: Wiederholtes Suchen in einem String, zuerst über die Zeichen, danach über die Wörter.

Hingegen erzeugt »std::sregex_token_iterator it2(str2.begin(),str2.end(),reg2,-1)« einen Iterator über alle Wörter aus dem gleichen String, die mit dem regulären Ausdruck »std::regex reg2(",")« gebildet wurden. Abbildung 1 zeigt den Unterschied zwischen dem Iterator über die Zeichen und dem über die Wörter. Für das Studium der Details bietet sich die Dokumentation der Reguläre-Ausdrücke-Bibliothek von Boost [8] an, die die Grundlage für die C++0x-Implementierung darstellt.

Listing 6: Suche mit einem
regulären Ausdruck

01 std::regex rgx(R"d+");
02 std::smatch match;
03 if (std::regex_search(std::string("123A43"), match, rgx))
04     std::cout << "match found after " << match.prefix() << 'n';

Listing 7: Wiederholtes Suchen
mit Regex

01 std::regex reg1("[^13579,]");
02 std::string str1="1,2,3,4,5,6,7,8,9,10,11,12";
03 std::sregex_iterator it1(str1.begin(),str1.end(),reg1);
04 std::sregex_iterator end1;
05 std::cout << "Character Stream: " << std::endl;
06 while (it1 != end1) std::cout << " " << *it1++;
07 std::cout << "nn";
08  
09 std::regex reg2(",");
10 std::string str2="1,2,3,4,5,6,7,8,9,10,11,12";
11 std::sregex_token_iterator it2(str2.begin(),str2.end(),reg2,-1);
12 std::sregex_token_iterator end2;
13 std::cout << "Token Stream: " << std::endl;
14 while (it2 != end2) std::cout << "  "  << *it2++;
15 std::cout << "n";

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • C++11

    Der Smart Pointer gilt als der klügste seiner Art in C++11. Sein Fachgebiet ist die elegante Garbage Collection, manchmal muss aber sein kleiner Bruder Weak Pointer mithelfen.

  • C++11

    Die neuen Smart Pointer in C++11 machen den Zugriff auf Ressourcen transparent und räumen hinter sich auf. Dieser Artikel stellt als ersten Vertreter den Unique Pointer vor.

  • C++11

    Klein, aber oho: Platziert ein Entwickler drei Punkte ("…") geschickt an der richtigen Stelle im C++-Code, entpacken die so genannten Variadic Templates ihre Argumente an Ort und Stelle.

  • C++11

    2014 ist ein besonderes Jahr für C++. Drei Jahre nach C++11 erfährt der Sprachstandard mit C++14 den letzten Feinschliff. Neben generischen Lambda-Funktionen und der vereinfachten Ermittlung des Rückgabetyps kann C++14 vor allem mit einem Feature punkten: Reader-Writer-Locks.

  • C++11

    Die Referenz-Wrapper bilden eine kleine, aber feine neue Bibliothek in C++11. Diese Objekte verhalten sich wie Referenzen, der Artikel erklärt die Details.

comments powered by Disqus

Ausgabe 11/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.