Ответ 1
При использовании std:: chrono:: nanoseconds вместо этого, это громоздко укажите, скажем, 10 минут.
На самом деле, это не делает его громоздким как минимум:
#include <chrono>
#include <iostream>
void my_function(bool work_really_hard, std::chrono::nanoseconds timeout)
{
std::cout << timeout.count() << '\n';
}
int
main()
{
my_function(true, std::chrono::minutes(10));
}
Вывод:
600000000000
Единственный раз, когда у вас возникнут проблемы с nanoseconds
, вы хотите передать то, что не будет точно конвертироваться в nanoseconds
, например picoseconds
или duration<long, ratio<1, 3>>
(1/3 секунды единиц).
Обновление
Я наметил этот ответ дополнительной информацией для уже принятого ответа, который, как я думал, был хорошим ответом (by sehe). sehe рекомендовал шаблонное решение, которое я также считаю прекрасным.
Если вы хотите принять любой std::chrono::duration
, даже тот, который вам может понадобиться обрезать или округлить, то переход с удаленным ответом - путь:
template <typename Rep, typename Period>
void my_function(bool work_really_hard, std::chrono::duration<Rep, Period> timeout)
{
// Do stuff, until timeout is reached.
std::this_thread::sleep_for(timeout);
}
Если по какой-то причине вы не хотите иметь дело с шаблонами и/или довольствуетесь тем, что ваши клиенты должны указывать только те единицы, которые в точности конвертируются в std::chrono:nanoseconds
, то использование std::chrono:nanoseconds
, как показано выше, также полностью приемлемый.
Все std::chrono
"предварительно определенные" единицы:
hours
minutes
seconds
milliseconds
microseconds
nanoseconds
неявно конвертируются в nanoseconds
и не будут включать в себя ошибки усечения или округления. Переполнение не произойдет, пока вы держите его в двух ярких белых линиях (неясная ссылка на то, чтобы держать свой автомобиль в своей полосе). Пока продолжительность составляет +/- 292 года, вам не нужно беспокоиться о переполнении этими заранее определенными единицами.
Определяемые std функции, такие как std::this_thread::sleep_for
, являются шаблонами, поскольку предполагает, что именно по этой причине желательно, чтобы они были интероперабельны с каждым chrono:duration
, который можно вообразить (например, 1/3 фемтосекунды с плавающей точкой). Разработчик API может решить, нужна ли им такая гибкость в своем API.
Если мне теперь удалось смутить вас, а не уточнить, не беспокойтесь слишком много. Если вы решите использовать nanoseconds
, все будет работать точно, без усечения или ошибки округления, или клиент получит ошибку времени компиляции. Будет ошибка нет.
void my_function(bool work_really_hard, std::chrono::nanoseconds timeout)
{
std::cout << timeout.count() << '\n';
}
int
main()
{
using namespace std;
using namespace std::chrono;
typedef duration<double, pico> picoseconds;
my_function(true, picoseconds(100000.25));
}
test.cpp:15:9: error: no matching function for call to 'my_function'
my_function(true, picoseconds(100000.25));
^~~~~~~~~~~
test.cpp:4:10: note: candidate function not viable: no known conversion from 'duration<double, ratio<[...], 1000000000000>>' to
'duration<long long, ratio<[...], 1000000000>>' for 2nd argument
void my_function(bool work_really_hard, std::chrono::nanoseconds timeout)
^
1 error generated.
И если клиент получает ошибку времени компиляции, он всегда может использовать duration_cast
, чтобы обойти его:
my_function(true, duration_cast<nanoseconds>(picoseconds(100000.25))); // Ok
Для получения дополнительной информации см.:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm
Сладкое обновление исходного кода в верхней части этого ответа. В С++ 1y, который, мы надеемся, означает С++ 14:
using namespace std::literals;
my_function(true, 10min); // also ok, is equal to 600000000000 nanoseconds
Вопрос: Что бы вы порекомендовали в качестве тайм-аута "бесконечности" (т.е. не время ожидания)
Сначала я попытался использовать API, который не использовал тайм-аут, и подразумевал, что "не тайм-аут". Например condition_variable::wait
. Если бы у меня был контроль над API, я бы создал такую подпись без тайм-аута.
В противном случае я бы создал серию "большой" chrono::durations
:
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
> days;
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<7>>
> weeks;
typedef std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<146097, 400>>
> years;
typedef std::chrono::duration
<
std::int32_t, std::ratio_divide<years::period, std::ratio<12>>
> months;
И затем я бы использовал одну из этих больших длительностей в моем вызове, например:
std::this_thread::sleep_for(years(3));
Я бы не пытался максимально увеличить push_things (вы можете нарушить базовые предположения, сделанные ОС, например). Просто произвольно выберите что-то смехотворно большое (например, 3 года). Это поймает ваш глаз обзора кода и, вероятно, заинтересует информативный разговор.: -)
Теперь доступно на видео: https://www.youtube.com/watch?v=P32hvk8b13M: -)