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