Open Source im professionellen Einsatz
Linux-Magazin 04/2016

Modernes C++ in der Praxis – Folge 27

Die Zeit verstehen

Die neue Zeitbibliothek ist ein elementarer Baustein nicht nur für die Mulithreading-Fähigkeit von C++. Mit ihrer Hilfe legt der Entwickler einen Thread bis zu einem definierten Zeitpunkt schlafen oder fordert auf gut Glück ein Lock für eine Zeitspanne an.

832

Neben ihrem Einsatz mit Threads und Locks bietet sich die Zeitbibliothek auch als Werkzeug für einfache Performance-Messungen an. Wer sie nutzen will, sollte sich allerdings zunächst mit der Theorie beschäftigen.

Zeitfrage

Ein so intuitives Konzept wie die Zeit offenbart erst auf den zweiten Blick seine immanente Komplexität. Die spiegelt sich in den Begriffen Zeitpunkt, Zeitdauer und Zeitgeber wider, die einer knappen Klärung bedürfen:

  • Zeitpunkt: Ein Zeitpunkt setzt sich aus einem Startpunkt, auch als Epoche bezeichnet, sowie einer darauf bezogenen Zeitdauer zusammen.
  • Zeitdauer: Die Zeitdauer ist die Differenz zwischen zwei Zeitpunkten. Sie lässt sich als Anzahl von Zeittakten messen.
  • Zeitgeber: Ein Zeitgeber besteht aus einem Startpunkt und einem Zeittakt. Über sie bestimmt ein Programmierer den aktuellen Zeitpunkt.

Zeitpunkte eignen sich für Vergleiche. Wer eine Zeitdauer zu einem Zeitpunkt addiert, erzeugt einen neuen Zeitpunkt. Der Zeittakt spiegelt die Granularität des Zeitgebers wider und dient als Messeinheit der Zeitdauer. In unserem Kulturkreis wäre etwa Christi Geburt der Startpunkt, als typischer Zeittakt gilt ein Jahr. Abbildung 1 erklärt die Konzepte am Beispiel einer fiktiven Person, die 1833 geboren wurde und 1863 ihren 30. Geburtstag feierte.

Abbildung 1: Das Konzept hinter den Begriffen Zeitpunkt, Zeitdauer und Zeittakt an einem Beispiel.

Den Startpunkt Christi Geburt sowie die Zeitdauer im Jahrestakt definieren die Zeitpunkte 1833 und 1863. Natürlich ist auch der Startpunkt ein Zeitpunkt. Wer das Jahr 1833 vom 1863 abzieht, erhält die Zeitdauer. Nach diesem allgemeinen Einstieg, folgen die Details im Bezug auf C++. Hier besitzt jeder der genannten Begriffe ein entsprechendes Pendant [1].

Zeitpunkt

Den Zeitpunkt legen ein Startpunkt (die erwähnte Epoche) und die darauf bezogene Zeitdauer fest (Listing 1). Dabei enthält ein Zeitpunkt einen Zeitgeber (Clock) und eine Zeitdauer (Duration). Letztere darf negativ oder positiv sein. Für die Zeitgeber stellt C++ die Klassen »std::chrono::system_clock« , »std::chrono::steady_clock« und »std:: chrono::high_resolution_clock« bereit. Mit ihnen berechnet der Chronologe in Listing 2 die Zeitdauer seit dem 1. Januar 1970 in mehreren Zeittakten.

Listing 1

Zeitpunkt

01 template <class Clock,class Duration= typename Clock::duration>
02 class time_point;

Listing 2

Zeitdauer-Varianten

01 #include <chrono>
02 #include <iostream>
03
04 int main(){
05
06   std::cout << std::fixed  std::endl;
07
08   auto timeNow= std::chrono::system_clock::now();
09   auto duration= timeNow.time_since_epoch();
10
11   std::cout << "time since 1.1.1970:" << std::endl;
12   std::cout << std::endl;
13
14   std::cout << duration.count() << " nanoseconds" << std::endl;
15
16   typedef std::chrono::duration<double> MySecondTick;
17   MySecondTick mySecond(duration);
18   std::cout << mySecond.count() << " seconds" << std::endl;
19
20   const int minute= 60;
21   typedef std::chrono::duration<double, std::ratio<minute>> MyMinuteTick;
22   MyMinuteTick myMinute(duration);
23   std::cout << myMinute.count() << " minutes" << std::endl;
24
25   const int hour= minute * 60;
26   typedef std::chrono::duration<double, std::ratio<hour>> MyHourTick;
27   MyHourTick myHour(duration);
28   std::cout << myHour.count() << " hours" << std::endl;
29
30   const int day= hour * 24;
31   typedef std::chrono::duration<double, std::ratio<day>> MyDayTick;
32   MyDayTick myDay(duration);
33   std::cout << myDay.count() << " days" << std::endl;
34
35   const int month= day * 30;
36   typedef std::chrono::duration<double, std::ratio<month>> MyMonthTick;
37   MyMonthTick myMonth(duration);
38   std::cout << myMonth.count() << " months" << std::endl;
39
40   const int year= month * 12;
41   typedef std::chrono::duration<double, std::ratio<year>> MyYearTick;
42   MyYearTick myYear(duration);
43   std::cout << myYear.count() << " years" << std::endl;
44
45   typedef std::chrono::duration<double, std::ratio<3600>> MyHourTick;
46   MyHourTick myOneHour(duration);
47   std::cout << myOneHour.count() << " hours" << std::endl;
48
49   typedef std::chrono::duration<double, std::ratio<2700>> MyLessonTick;
50   MyLessonTick myLesson(duration);
51   std::cout << myLesson.count() << " lessons" << std::endl;
52
53   std::cout << std::endl;
54
55 }

In Zeile 8 ermittelt der Ausdruck »timeNow.time_since_epoch()« die Zeitdauer seit dem 1.1.1970 im Falle des Zeitgebers »std::chrono::system_clock« . Das Programm rechnet den Wert in die Zeittakte Nanosekunde (Zeile 14), Sekunde (Zeile 18), Minute (Zeile 23), Stunde (Zeile 28), Tag (Zeile 33), Monat (Zeile 38) und Jahr (Zeile 43) um. Der Entwickler definiert zudem eigene Zeittakte:

typedef std::chrono::duration<double,  std::ratio<2700>> MyLessonTick

Der Datentyp »MyLessonTick« gibt Werte im Drei-Viertelstunden-Takt aus.

Der Datentyp »std::ratio« steht für eine Bruchzahl. Standardmäßig erhalten Nenner und Zähler den Wert 1. Beispielsweise steht der Ausdruck »std::ratio<2700>« für »std::ratio<2700,1>« . Dieser Wert repräsentiert 2700 Sekunden, denn die Grundeinheit sind Sekunden. 2700 Sekunden sind 45 Minuten und entsprechen damit der Länge einer klassischen Schulstunde (Zeile 49). Abbildung 2 zeigt die Ausgabe des Programms.

Abbildung 2: Die seit dem 1. Januar 1970 verstrichene Zeit, dargestellt in verschiedenen Zeittakten.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

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

Deutschland

Ähnliche Artikel

  • 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 neue Zeitbibliothek von C++11 erweist sich als elementarer Bestandteil der Threading-Schnittstelle: Sowohl Threads, Locks und Bedingungsvariablen als auch Futures haben ein Verständnis von Zeit. Dank ihrer Unterstützung kann ein Entwickler unterschiedliche Wartestrategien verfolgen.

  • C++11

    "Performance matters": Was sich wie ein Glaubensbekenntnis anhört, bleibt ein wichtiges Designkriterium in C++. Mit den neuen Hashtabellen kann der Programmierer richtig Tempo machen.

  • C++11

    C++-Code sicherer machen und zugleich an der Performance-Schraube drehen, das sind die beiden Domänen der neuen Type-Traits-Bibliothek. Sie beschleunigt Code, indem sie Typen zur Kompilierzeit analysiert und verändert, wenn der Entwickler sie geschickt einsetzt.

  • C++11

    In C++11 lässt sich manches prägnanter formulieren als in klassischem C++. Dieser Artikel zeigt, wie die neue Range-basierte For-Schleife und die automatische Typableitung dabei helfen.

comments powered by Disqus

Ausgabe 04/2017

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