c++ - 使用 std::chrono::duration 跟踪超时

标签 c++ c++11

我有一个函数,它以 long 形式获取超时发生之前的微秒数。此超时是函数完成其工作的超时,即使由于调度和其他开销等原因,函数可能需要比超时更长的时间。

该函数执行以下操作:

  1. 使用 std::futurestd::async 执行一些设置并启动多个线程。
  2. 在循环中使用 std::future::wait_for() 跟踪线程。基本上,我对每次调用 wait_for() 进行计时,并从超时中减去所花费的时间。然后在检查下一个线程时使用这个新的超时。我的目标是确保我启动的所有线程在超时(即传递给函数的超时参数)到期之前完成其工作。

伪代码如下:

void myFunctionWithTimeout(/*some other inputs*/ const long timeout_us) {
  auto start_time = std::chrono::steady_clock::now();
  double time_remaining_us = std::chrono::microseconds(timeout_us).count();

  // Launch threads here using std::future and std::async...

  auto end_time = std::chrono::steady_clock::now();
  const auto setup_time_us =
    std::chrono::duration<double, std::micro>(end_time - start_time);
  time_remaining_us -= setup_time_us.count();

  for(auto& worker : workers) {
    auto start_time = std::chrono::steady_clock::now();
    const auto status =
      worker.wait_for(std::chrono::duration<double, std::micro>(time_remaining_us));
    auto end_time = std::chrono::steady_clock::now();

    // Check status and do the appropriate actions.
    // Note that it is OK that this time isn't part of the timeout.

    const auto wait_time_us =
      std::chrono::duration<double, std::micro>(end_time - start_time);
    time_remaining_us -= wait_time_us.count();
  }
}

我的问题:

  1. 是否有更简单的方法来实现我的建议?我的目标是将剩余时间存储为 double ,以便在各种计算中我可以考虑到微秒的几分之一。请注意,我知道由于调度和其他原因, wait_for() 不会完全等待我指定的持续时间,但至少,我不想添加任何舍入我的计算出现错误。
  2. 与 #1 相关:我是否需要每次都获取计数,或者是否有一种干净的方法来更新 std::chrono::duration?我希望将剩余时间存储为持续时间,然后从中减去设置时间或等待时间。
  3. time_remaining_us 变为负数时会发生什么?这对 std::chrono::duration 的构造函数有何影响?当负持续时间传递给 std::future::wait_for() 时会发生什么?我没有在文档中找到这些详细信息,我想知道这里的行为是否定义良好。

================================================== ===================== 编辑添加:

根据霍华德的回答,我研究了使用wait_until(),但我认为它对我不起作用,因为我在研究中发现了以下问题(摘录自:https://en.cppreference.com/w/cpp/thread/future/wait_until ):

The clock tied to timeout_time is used, which is not required to be a monotonic clock.There are no guarantees regarding the behavior of this function if the clock is adjusted discontinuously, but the existing implementations convert timeout_time from Clock to std::chrono::system_clock and delegate to POSIX pthread_cond_timedwait so that the wait honors ajustments to the system clock, but not to the the user-provided Clock. In any case, the function also may wait for longer than until after timeout_time has been reached due to scheduling or resource contention delays.

我的理解是,即使我使用 steady_clock 作为结束时间,它也会转换为 system_clock,这意味着如果时钟被调整(假设回滚一小时)我最终可能会遇到比我预期长得多的超时。

也就是说,我确实采用了计算结束时间的概念,它简化了我的代码。这是我目前所处位置的一些伪代码:

void myFunctionWithTimeout(/*some other inputs*/ const long timeout_us) {
  const auto start_time = std::chrono::steady_clock::now();
  const auto end_time =
    start_time + std::chrono::duration<double, std::micro>(timeout_us);

  // Launch threads here using std::future and std::async...

  for(auto& worker : workers) {
    const auto current_timeout_us =
      std::chrono::duration<double, std::micro>(end_time - std::chrono::steady_clock::now());
    if (current_timeout_us.count() <= 0) {  // Is this needed?
      // Handle timeout...
    }
    const auto status = worker.wait_for(current_timeout_us);

    // Check status and do the appropriate actions...
  }
}

我仍然不确定是否可以将负持续时间传递给 wait_for(),因此我首先手动检查。如果有人知道 wait_for() 是否可以接受负持续时间,请告诉我。另外,如果我对 wait_until() 文档的理解不正确,也请告诉我。

最佳答案

只需使用wait_until而不是wait_for。计算您想要等待一次的time_point,并继续使用它。如果该 time_point 开始落入过去,wait_until 将立即返回。

关于c++ - 使用 std::chrono::duration 跟踪超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52249068/

相关文章:

c++ - 64 位 SendMessage API

c++ - 具有智能指针类的 VS2008 中的 STLPort 模糊复制构造函数

c++ - 每次我到处使用结构而不是类时,我会杀死一只小猫吗?

c++ - c++将equal_to设置为模板类的默认模板参数

c++ - 我需要在 pthread_mutex_destroy 之后使用 delete

c++ - 调用虚拟方法而不是派生方法

C++11 Cereal 库无法序列化我的类

c++ - 在 C++ 中计算 10^9 中的数字

C++11 字符串的分配要求

c++ - 为什么对原始类型的操作是无序的而不是不确定的顺序?