4.3.2. Временные интервалы

Интервалы — самая простая часть подсистемы поддержки времени; они представлены шаблонным классом std::chrono::duration<> (все имеющиеся в С++ средства работы со временем, которые используются в библиотеке Thread Library, находятся в пространстве имен std::chrono). Первый параметр шаблона — это тип представления (int, long или double), второй — дробь, показывающая, сколько секунд представляет один интервал. Например, число минут, хранящееся в значении типа short, равно std::chrono::duration<short, std::ratio<60,1>>, потому что в одной минуте 60 секунд. С другой стороны, число миллисекунд, хранящееся в значении типа double, равно std::chrono::duration<double, std::ratio<1, 1000>>, потому что миллисекунда — это 1/1000 секунды.

В пространстве имен std::chrono имеется набор предопределенных typedef'ов для различных интервалов: nanoseconds, microseconds, milliseconds, seconds, minutes и hours. В них используется достаточно широкий целочисленный тип, подобранный так, чтобы можно было представить в выбранных единицах интервал продолжительностью свыше 500 лет. Имеются также typedef для всех определенных в системе СИ степеней 10 — от std::atto (10-18) до std::exa (1018) (и более, если платформа поддерживает 128-разрядные целые числа) — чтобы можно было определить нестандартные интервалы, например std::duration<double, std::centi> (число сотых долей секунды, хранящееся в значении типа double).

Между типами интервалов существует неявное преобразование, если не требуется отсечение (то есть неявно преобразовать часы в секунды можно, а секунды в часы нельзя). Для явного преобразования предназначен шаблон функции std::chrono::duration_cast<>:

std::chrono::milliseconds ms(54802);

std::chrono::seconds s =

 std::chrono::duration_cast<std::chrono::seconds>(ms);

Результат отсекается, а не округляется, поэтому в данном примере s будет равно 54.

Для интервалов определены арифметические операции, то есть сложение и вычитание интервалов, а также умножение и деление на константу базового для представления типа (первый параметр шаблона) дает новый интервал. Таким образом, 5*seconds(1) — то же самое, что seconds(5) или minutes(1) - seconds(55). Количество единиц в интервале возвращает функция-член count(). Так, std::chrono::milliseconds(1234).count() равно 1234.

Чтобы задать ожидание в течение интервала времени, используется функция std::chrono::duration<>. Вот, например, как задается ожидание готовности будущего результата в течение 35 миллисекунд:

std::future<int> f = std::async(some_task);

if (f.wait_for(std::chrono::milliseconds(35)) ==

    std::future_status::ready)

 do_something_with(f.get());

Все функции ожидания возвращают код, показывающий, истек ли таймаут или произошло ожидаемое событие. В примере выше мы ожидаем будущий результат, поэтому функция вернет std::future_status::timeout, если истек таймаут, std::future_status::ready — если результат готов, и std::future_status::deferred — если будущая задача отложена. Время ожидания измеряется с помощью библиотечного класса стабильных часов, поэтому 35 мс — это всегда 35 мс, даже если системные часы были подведены (вперёд или назад) в процессе ожидания. Разумеется, из-за особенностей системного планировщика и варьирующейся точности часов ОС фактическое время между вызовом функции в потоке и возвратом из нее может оказаться значительно больше 35 мс.

Разобравшись с интервалами, мы можем перейти к моментам времени.