0

データのタイムスタンプを見て、データが 120 秒 (または 2 分) 古いかどうかを確認しようとしているのでchrono、C++ でパッケージを使用しているため、以下のコードがあります。

uint64_t now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
// check for 2 minutes old data
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));   

uint64_t value = now;
while (now < data_holder->getTimestamp() + 80 * 1000 
        && now < value + 80 * 1000) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}

上記のコードのdata_holder->getTimestamp()uint64_t は、ミリ秒単位でタイムスタンプを返します。

now変数値を印刷すると、これが表示され、値10011360を印刷するとdata_holder->getTimestamp()1437520382241

2015-07-21 16:13:02,530 WARN 0x7f35312d1700 data_check - now value: 10011360 , data holder timestamp: 1437520382241

そして、上記のデータホルダーのタイムスタンプから、120 秒前のデータではないように見えるので、コードに何か問題があると感じますか? そのデータホルダーのタイムスタンプを(エポックコンバーターを使用して)実際の時間に変換し、上記のようにログ時間と比較すると、ほぼ同じになります。

そこで、代わりに を使用することにし、system_clock代わりにをsteady_clock使用し始めた以下のコードを思いつきました。autouint64_t

ソリューション A:

auto now = system_clock::now();
auto dh_ts = system_clock::time_point{milliseconds{data_holder->getTimestamp()}};
bool is_old = (minutes{2} < (now - dh_ts));

以前は、now変数の値をuint64_tの代わりに使用していましautoた。上記のコードの後、元のコードにこのようなものがあるので、そうでnowはないuint64_tため、コードのコンパイル中にコンパイルエラーが発生します。

uint64_t value = now;
while (now < data_holder->getTimestamp() + 80 * 1000 
        && now < value + 80 * 1000) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    now = duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
}

これを修正する正しい方法は何ですか? data_holder->getTimestamp()データ型を変更できませんuint64_t。他のコードでも使用されているためです。

エラーは次のとおりです。

error: cannot convert std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long int, std::ratio<1l, 1000000000l> > >â to âuint64_t {aka long unsigned int}â in initialization

アップデート:

Solution A以下のすべてが良さそうに見える場合に使用する代わりに、このように使用できますか?

ソリューション B:

uint64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
bool is_old = (120 * 1000 < (now - data_holder->getTimestamp()));
4

2 に答える 2

2

少なくとも私が読んだ限りでは、これは一度に 100 ミリ秒スリープしてから、まだ 2 分間スリープしているかどうかを確認しています。その後、2分ポイントに達するまで繰り返します。

希望の時間を計算し、それまでスリープする方がはるかに理にかなっているように私には思えます:

struct foo { 
    time_point<system_clock> time_stamp;

    time_point<system_clock> get_timestamp() { return time_stamp; }
    foo() : time_stamp(system_clock::now()) {}
};

// ...    
foo f;

std::this_thread::sleep_until(f.get_timestamp() + 2m);

これは、(C++14 の新機能) ユーザー定義リテラルを使用して 2 分の期間を構築します。古い (C++11) コンパイラを本当にサポートする必要がある場合は、minutes(2)代わりに使用する必要があります。

タイトルの質問に関する限り、私はこう言いたいです。time_points を整数に詰め込むことを主張するよりも、実際の time_points として保存し、再度使用する必要があるときに time_points に戻す方がはるかに優れています。これが痛みと引き換えに何か有用なことを達成することはまったく明らかではありません.

于 2015-07-23T01:30:54.683 に答える
0

実際には、解決策 A の方向に進み、残りのuint64_t時間を time_pointsに変換することをお勧めしますchrono。単位系は非常に便利です。uint64_tオブジェクトのタイムスタンプを time_pointsに変換するヘルパー関数を定義することから始めます。

using u64_millis = duration<uint64_t, milli>;
static time_point<system_clock, u64_millis> u64_to_time(uint64_t timestamp) {
    return time_point<system_clock, u64_millis>{u64_millis{timestamp}};
}

エポックが のエポックと異なる場合はsystem_clock、ここで修正します。millisecondsの代わりに使用することもおそらく機能しますu64_millisが、の表現型millisecondsは明示的に定義されておらず、上記の方法で行うと、型が正しく一致することが保証されます。

さて、投稿したコードは次のようになります。

auto now = system_clock::now();
bool is_old = now - u64_to_time(data_holder->getTimestamp()) > minutes{2};

auto value = now;
while (now - u64_to_time(data_holder->getTimestamp()) < seconds{80}
        && now - value < seconds{80}) {
    this_thread::sleep_for(milliseconds{100});
    now = system_clock::now();
}
于 2015-07-23T01:04:13.597 に答える