Как преобразовать std::chrono::time_point в uint64_t?

Я пытаюсь выяснить, устарели ли мои данные 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 и придумал код ниже, в котором я начал использовать auto вместо uint64_t,

Решение А:

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 если все выглядит хорошо ниже?

Решение Б:

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

2 ответа

Решение

На самом деле, я бы посоветовал пойти дальше в сторону решения А и преобразовать остальные ваши 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();
}

По крайней мере, пока я читаю, он спит 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, когда вам нужно будет использовать их снова. Совершенно не очевидно, что это приносит пользу в обмен на боль.

Другие вопросы по тегам