Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
- Название:Параллельное программирование на С++ в действии. Практика разработки многопоточных программ
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-448-1
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Энтони Уильямс - Параллельное программирование на С++ в действии. Практика разработки многопоточных программ краткое содержание
Книга «Параллельное программирование на С++ в действии» не предполагает предварительных знаний в этой области. Вдумчиво читая ее, вы научитесь писать надежные и элегантные многопоточные программы на С++11. Вы узнаете о том, что такое потоковая модель памяти, и о том, какие средства поддержки многопоточности, в том числе запуска и синхронизации потоков, имеются в стандартной библиотеке. Попутно вы познакомитесь с различными нетривиальными проблемами программирования в условиях параллелизма.
Параллельное программирование на С++ в действии. Практика разработки многопоточных программ - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Если часы ходят с постоянной частотой (вне зависимости от того, совпадает эта частота с period
или нет) и не допускают подведения , то говорят, что часы стабильны . Статический член is_steady
класса часов равен true
, если часы стабильны, и false
в противном случае. Как правило, часы std::chrono::system_clock
нестабильны, потому что их можно подвести, даже если такое подведение производится автоматически, чтобы учесть локальный дрейф. Из-за подведения более позднее обращение к now()
может вернуть значение, меньшее, чем более раннее, а это нарушение требования к равномерному ходу часов. Как мы скоро увидим, стабильность важна для вычислений с таймаутами, поэтому в стандартной библиотеке С++ имеется класс стабильных часов — std::chrono::steady_clock
. Помимо него, стандартная библиотека содержит класс std::chrono::system_clock
(уже упоминавшийся выше), который представляет системный генератор «реального времени» и имеет функции для преобразования моментов времени в тип time_t
и обратно, и класс std::chrono::high_resolution_clock
, который представляет наименьший возможный тактовый период (и, следовательно, максимально возможное разрешение). Может статься, что этот тип на самом деле является псевдонимом typedef
какого-то другого класса часов. Все эти классы определены в заголовке наряду с прочими средствами работы со временем.
Чуть ниже мы рассмотрим представления моментов времени, но сначала познакомимся с представлением интервалов.
4.3.2. Временные интервалы
Интервалы — самая простая часть подсистемы поддержки времени; они представлены шаблонным классом std::chrono::duration<>
(все имеющиеся в С++ средства работы со временем, которые используются в библиотеке Thread Library, находятся в пространстве имен std::chrono
). Первый параметр шаблона — это тип представления ( int
, long
или double
), второй — дробь, показывающая, сколько секунд представляет один интервал. Например, число минут, хранящееся в значении типа short
, равно std::chrono::duration<60,1>>
, потому что в одной минуте 60 секунд. С другой стороны, число миллисекунд, хранящееся в значении типа double
, равно std::chrono::duration<1, 1000>>
, потому что миллисекунда — это 1/1000 секунды.
В пространстве имен std::chrono
имеется набор предопределенных typedef
'ов для различных интервалов: nanoseconds
, microseconds
, milliseconds
, seconds
, minutes
и hours
. В них используется достаточно широкий целочисленный тип, подобранный так, чтобы можно было представить в выбранных единицах интервал продолжительностью свыше 500 лет. Имеются также typedef
для всех определенных в системе СИ степеней 10 — от std::atto
(10 -18) до std::exa
(10 18) (и более, если платформа поддерживает 128-разрядные целые числа) — чтобы можно было определить нестандартные интервалы, например std::duration
(число сотых долей секунды, хранящееся в значении типа double
).
Между типами интервалов существует неявное преобразование, если не требуется отсечение (то есть неявно преобразовать часы в секунды можно, а секунды в часы нельзя). Для явного преобразования предназначен шаблон функции std::chrono::duration_cast<>
:
std::chrono::milliseconds ms(54802);
std::chrono::seconds s =
std::chrono::duration_cast(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 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 мс.
Разобравшись с интервалами, мы можем перейти к моментам времени.
4.3.3. Моменты времени
Момент времени представляется конкретизацией шаблона класса std::chrono::time_point<>
, в первом параметре которой задаются используемые часы, а во втором — единица измерения (специализация шаблона std::chrono::duration<>
). Значением момента времени является промежуток времени (измеряемый в указанных единицах) с некоторой конкретной точки на временной оси, которая называется эпохой часов. Эпоха часов — это основополагающее свойство, однако напрямую его запросить нельзя, и в стандарте С++ оно не определено. Из типичных эпох можно назвать полночь (00:00) 1 января 1970 года и момент, когда в последний раз был загружен компьютер, на котором исполняется приложение. У разных часов может быть общая или независимые эпохи. Если у двух часов общая эпоха, то псевдоним типа typedef time_point
в одном классе может ссылаться на другой класс как на тип, ассоциированный с time_point
. Хотя узнать, чему равна эпоха, невозможно, вы можете получить время между данным моментом time_point
и эпохой с помощью функции-члена time_since_epoch()
, которая возвращает интервал.
Например, можно задать момент времени std::chrono::time_point
. Он представляет время по системным часам, выраженное в минутах, а не в естественных для этих часов единицах (как правило, секунды или доли секунды).
К объекту std::chrono::time_point<>
можно прибавить интервал или вычесть из него интервал — в результате получится новый момент времени. Например, std::chrono::high_resolution_clock::now() + std::chrono::nanoseconds(500)
соответствует моменту времени в будущем, который отстоит от текущего момента на 500 наносекунд. Это удобно для вычисления абсолютного таймаута, когда известна максимально допустимая продолжительность выполнения некоторого участка программы, и внутри этого участка есть несколько обращений к функциям с ожиданием или обращения к функциям, которые ничего не ждут, но предшествуют функции с ожиданием и занимают часть отведенного времени.
Интервал:
Закладка: