Ich versuche zu sehen, ob meine Daten 120 Sekunden alt sind oder nicht, indem ich auf den Zeitstempel der Daten schaue, also habe ich den folgenden Code:
%Vor% Im obigen Code data_holder->getTimestamp()
ist uint64_t, der den Zeitstempel in Millisekunden zurückgibt.
Jetzt, wenn ich now
Variablenwert ausdrucke, sehe ich 10011360
und wenn ich data_holder->getTimestamp()
Wert ausdrucke das ist 1437520382241
, also sollte die Differenz von jetzt und Datenhalter Zeitstempel negativ sein, oder? Warum kommt es so positiv wie in den folgenden Logs gezeigt?
Sieht mein Code oben richtig aus? Und aus dem obigen Zeitstempel des Datenhalters sieht es nicht so aus, als wären es 120 Sekunden alte Daten, also habe ich das Gefühl, dass in meinem Code etwas nicht stimmt? Da, wenn ich den Zeitstempel des Dateninhabers in die tatsächliche Zeit umwandele (unter Verwendung des Epochenkonverters) und dann wie oben gezeigt mit der Protokollzeit vergleiche, ist es fast gleich.
Ich verwende steady_clock
wie oben gezeigt. Muss ich system_clock
hier benutzen? Was ist der Unterschied zwischen steady_clock
vs system_clock
in Laien. Ich führe diesen Code auf Ubuntu 14.04 Box.
Fragen in umgekehrter Reihenfolge beantworten:
Was ist der Unterschied zwischen
steady_clock
vssystem_clock
in Laien Begriffe.
Wenn Sie ein system_clock
in Ihrer Hand halten, würden Sie es eine Uhr nennen, und es würde Ihnen sagen, wie spät es ist.
Wenn Sie ein steady_clock
in Ihrer Hand halten, würden Sie es eine Stoppuhr nennen, und es würde Ihnen sagen, wie schnell jemand eine Runde gefahren ist, aber es würde Ihnen nicht sagen, wie spät es ist es ist.
Wenn Sie müssten, könnten Sie jemanden mit Ihrer Uhr eine Runde rennen lassen. Aber wenn Ihre Uhr (wie meine) regelmäßig mit einer anderen Maschine (wie der Atomuhr in Boulder CO) redet, um sich selbst auf die aktuelle Zeit zu korrigieren, könnte es kleinere Fehler beim Timing dieser Runde geben. Die Stoppuhr wird diesen Fehler nicht machen, aber sie kann Ihnen auch nicht sagen, was die korrekte aktuelle Zeit ist.
Sieht mein Code oben richtig aus?
Nein. Und selbst wenn es Ihnen vernünftige Antworten geben würde, würde ich nicht sagen, dass es richtig ist. Fühle dich nicht schlecht, das ist ein Anfängerfehler, den viele Leute mit der <chrono>
-Bibliothek machen.
Es gibt eine einfache Regel, der ich mit der <chrono>
-Bibliothek folge. Die Regel ist eigentlich nicht ganz korrekt (also ist es eine Richtlinie). Aber es ist nah genug, um eine Richtlinie zu sein, die fast immer befolgt wird:
Verwenden Sie nicht
count()
.
Und eine logische Folge:
Verwenden Sie nicht
time_since_epoch()
.
Die <chrono>
-Bibliothek wurde um ein typsicheres -System herum entwickelt, das Sie vor Fehlern bei der Konvertierung von Einheiten schützen soll. Wenn Sie versehentlich eine unsichere Konvertierung versuchen, wird der Fehler zur Kompilierungszeit abgefangen (im Gegensatz zu einem Laufzeitfehler).
Die Memberfunktionen count()
und time_since_epoch()
sind "Escape-Luken" aus diesem typsicheren System ... die nur in Notfällen verwendet werden sollen. Solche Notfälle entstehen, wenn (zum Beispiel) das Komitee es versäumt, Ihnen alle Werkzeuge zur Verfügung zu stellen, die Sie benötigen, um die Arbeit zu erledigen (wie I / O) für die <chrono>
-Typen oder wie die Notwendigkeit, mit einer anderen Timing-API zu interagieren über Ganzzahlen.
Überprüfen Sie Ihren Code und andere für die Verwendung von count()
und time_since_epoch()
und überprüfen Sie jede Verwendung dieser Funktionen: Gibt es any wie der Code neu geschrieben werden könnte, um ihre Verwendung zu beseitigen?
Überprüfen Sie die erste Zeile Ihres Codes:
%Vor% now
ist ein time_point
(von steady_clock
). Es sind Einheiten milliseconds
, aber zu dieser Zeit bin ich nicht davon überzeugt, dass die Einheiten wichtig sind. Wichtig ist, dass now
ein time_point
ist, das von steady_clock
abgerufen wurde:
Ihre zweite Zeile ist komplizierter:
%Vor% Beginnen wir mit data_holder->getTimestamp()
: Wenn Sie getTimestamp()
ändern können, sollten Sie sie so ändern, dass ein time_point
anstelle eines uint64_t
zurückgegeben wird. Um dies zu tun, müssen Sie die richtigen Einheiten kennen (was Sie tun - Millisekunden), und Sie müssen die richtige Epoche kennen. Die Epoche ist der Zeitpunkt, ab dem Ihre Millisekunden gemessen werden.
In diesem Fall ist 1437520382241ms ungefähr 45,6 Jahre alt. Angenommen, dies ist ein neuer Zeitstempel, vor 45,6 Jahren war sehr nahe am 1970-01-01. Wie sich herausstellt, verwendet jede Implementierung von system_clock()
1970-01-01 als seine Epoche (obwohl jede Implementierung unterschiedliche Einheiten aus dieser Epoche zählt).
Entweder ändern Sie getTimestamp()
, um eine time_point<system_clock, milliseconds>
zurückzugeben, oder umbrechen Sie die Rückgabe von getTimestamp()
mit time_point<system_clock, milliseconds>
:
Jetzt ist deine zweite Zeile:
%Vor%Eine weitere gute Richtlinie:
%Vor%Wenn Sie in Ihrem
<chrono>
-Code Umrechnungsfaktoren sehen, tun Sie es falsch.<chrono>
lebt für die Konvertierung für Sie.
Dieser nächste Schritt ist stilistisch, aber jetzt ist Ihr Code einfach genug, um Ihre überschüssigen Klammern loszuwerden, wenn Ihnen das gefällt:
%Vor% Wenn Sie die getTimestamp()
ändern können, um einen typsicheren Wert zurückzugeben, könnte dieser Code auch wie folgt aussehen:
Ach, auf jeden Fall kompiliert das noch nicht! Die Fehlermeldung sollte etwas in der Art sagen, dass es kein gültiges operator-()
zwischen now
und dh_ts
gibt.
Dies ist das Typ-Sicherheitssystem, das Sie vor Laufzeitfehlern schützt!
Das Problem ist, dass time_point
s von system_clock
nicht von time_point
s von steady_clock
subtrahiert werden kann (weil die beiden unterschiedliche Epochen haben). Du musst also zu:
Alles zusammenfügen:
%Vor%Und in C ++ 14 kann die letzte Zeile etwas übersichtlicher gestaltet werden:
%Vor%Zusammenfassend:
count()
(außer für E / A) nicht. time_since_epoch()
(außer für E / A) nicht. Wenn Sie in den obigen vier Punkten erfolgreich sind, werden Sie höchstwahrscheinlich keine Laufzeitfehler feststellen (aber Sie erhalten einen fairen Anteil an Kompilierzeitfehlern).
Der Grund dafür, dass Sie einen positiven Wert sehen, ist der unsigned integer wrap-around. Versuchen Sie es und sehen Sie:
%Vor% Wird der Wert von getTimestamp()
erwartet? Wenn nicht, ist es etwas schwierig zu sehen, was falsch ist, ohne die Implementierung von getTimestamp()
zu sehen. Es sieht so aus, als ob der Zeitstempel nicht mit der gleichen Uhr gemessen wurde.
Die stabile Uhr eignet sich am besten zum Messen von Zeitintervallen. Um aus cppreference.com zu zitieren:
Klasse std :: chrono :: steady_clock repräsentiert eine monotone Uhr. Die Zeitpunkte dieser Uhr können nicht abnehmen, wenn sich die physische Zeit vorwärts bewegt. Diese Uhr bezieht sich nicht auf die Wanduhrzeit und eignet sich am besten für die Messung von Intervallen.
Im Gegensatz zur system_clock, die nicht monoton ist (d. h. die Zeit kann sich verringern, wenn der Benutzer beispielsweise die Zeit auf dem Hostcomputer ändert.)
Erste Frage, negative Ganzzahl wird implizit umgewandelt, indem Sie eine Ganzzahl vom Typ "uint64_t" wird und eine riesige positive Ganzzahl wird.
Zweite Frage, system_clock ist eine systemweite Echtzeituhr, und wenn Sie die Systemzeit geändert haben, hat sich die Rückkehrzeit von system_clock geändert. Die steady_clock ist eine physikalische Zeit, so dass Sie sie nicht ändern können.