Какой тип использовать для переменной timeout в C++?
при написании функции на C++, которая принимает тайм-аут в качестве одного из своих аргументов, какой тип следует использовать для самого аргумента тайм-аута?
примером такой функции может быть:
void my_function(bool work_really_hard, timeout_type timeout)
{
// Do stuff, until timeout is reached.
}
Я думал об использовании std::chrono::seconds
на timeout_type
, но это запрещает использовать любой тайм-аут в субсекундной области.
при использовании , это громоздко, чтобы указать, скажем, 10 минут.
любой способ решить эту проблему в разумный способ, сохраняя при этом подпись функции и вызовы аккуратными и простыми?
2 ответов
при использовании std::chrono:: наносекунды вместо этого, это громоздко указать, скажем, 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 секунды блоки.)
обновление
я предполагал, что этот ответ будет дополнительной информацией для уже принятого ответа, который я считал хорошим ответом (sehe). sehe рекомендовал шаблонное решение, которое я также считаю прекрасным.
если вы хотите принять любой std::chrono::duration
, даже тот, который вам, возможно, придется truncate или круглые, то идти с удаленным ответом sehe-это путь:
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
являются шаблонными, как предлагает sehe именно по причине желания быть совместимыми с каждым 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
сладкое обновление исходного кода в верхней части этого ответа. В C++1y, что, как мы надеемся, означает C++14:
using namespace std::literals;
my_function(true, 10min); // also ok, is equal to 600000000000 nanoseconds
вопрос: что бы вы рекомендовали в качестве тайм-аута " бесконечности "(т. е. не тайм-аут)
я бы сначала попытался использовать API, который не взял тайм-аут, и который подразумевал "не тайм-аут.- Например! .. --22-->. Если бы у меня был контроль над API, я бы создал такую подпись без таймаута.
в противном случае я бы создал серию "большой" chrono::durations
:
using days = std::chrono::duration
<
std::int32_t, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
>;
using weeks = std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<7>>
>;
using years = std::chrono::duration
<
std::int32_t, std::ratio_multiply<days::period, std::ratio<146097, 400>>
>;
using months = std::chrono::duration
<
std::int32_t, std::ratio_divide<years::period, std::ratio<12>>
>;
и тогда я бы использовал одну из этих больших длительностей в моем вызове, например:
std::this_thread::sleep_for(years(3));
я не попытаюсь push_things по максимуму (вы можете нарушить основополагающие допущения ОС сделал например). Просто произвольно выберите что-то смехотворно большое (например, 3 года). Что будет ловить ваш код рецензента глаз, и, вероятно, начать информативный разговор. :-)
теперь доступно в видео:https://www.youtube.com/watch?v=P32hvk8b13M :-)
используйте параметр шаблона для типа тайм-аута и ожидайте одного из std::chrono
типы или что-то с аналогичным интерфейсом; это позволит вам пройти в любой единице времени.
template<typename T>
void wait_a_while(const T& duration)
{
std::this_thread::sleep(duration);
}
wait_a_while(boost::posix_time::seconds(5));
wait_a_while(std::chrono::milliseconds(30));