Какой тип использовать для переменной 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));