【问题标题】:c++ wait_until strange timeout behaviourc++ wait_until 奇怪的超时行为
【发布时间】:2018-05-21 11:00:27
【问题描述】:

我正在尝试用 C++ 编写一种线程池。该代码在 OSX 中运行良好,但在 Linux 下我遇到了一种奇怪的行为。 经过一番调试,我发现问题是由于对 std::condition_variable::wait_until 的调用,我必须以错误的方式进行操作。

使用下面的代码,我希望循环每三秒循环一次:

#include <mutex>
#include <chrono>
#include <iostream>
#include <memory>
#include <condition_variable>
#include <thread>

using namespace std;

typedef std::chrono::steady_clock                           my_clock;
typedef std::chrono::duration<float, std::ratio<1> >        seconds_duration;
typedef std::chrono::time_point<my_clock, seconds_duration> timepoint;

timepoint my_begin = my_clock::now();

float timepointToFloat(timepoint time) {
  return time.time_since_epoch().count() - my_begin.time_since_epoch().count();
}

void printNow(std::string mess) {
  timepoint now = my_clock::now();
  cout << timepointToFloat(now) << " " << mess  << endl;;
};

void printNow(std::string mess, timepoint time ) {
  timepoint now = my_clock::now();
  cout << timepointToFloat(now) << " " << mess  << " " << timepointToFloat(time) << endl;;
};

int main() {
  mutex _global_mutex;
  condition_variable _awake_global_execution;
  auto check_predicate = [](){
    cout << "predicate called" << endl;
    return false;
  };

  while (true) {
    { // Expected to loop every three seconds
      unique_lock<mutex> lock(_global_mutex);
      timepoint planned_awake = my_clock::now() + seconds_duration(3);
      printNow("wait until", planned_awake);
      _awake_global_execution.wait_until(lock, planned_awake, check_predicate);
    }
    printNow("finish wait, looping");
  }

  return 0;
}

但是,有时我会得到输出:

<X> wait until <X+3>
predicate called
(...hangs here for a long time)

(其中 X 是一个数字),因此似乎没有在三秒后安排超时。有时我会得到:

<X> wait until <X+3>
predicate called
predicate called
<X> finish wait, looping
<X> wait until <X+3> (another loop)
predicate called
predicate called
<X> finish wait, looping
(...continue looping without waiting)

所以看起来超时是在几秒钟后安排的。我想我在超时时间点上搞砸了,但我无法弄清楚我做错了什么。

如果可能相关,此代码在 OSX 中运行良好,而在 Linux(Ubuntu 16.04,gcc 5.4,使用“g++ main.cc -std=c++11 -pthread”编译)我遇到了奇怪的问题行为。

我怎样才能让它工作?

【问题讨论】:

  • 在等待之前,您需要确保等待的事情尚未发生。在你决定不等待之前,你必须确保你等待的事情已经发生了。条件变量是无状态的,不知道你在等待什么或者它是否发生了。跟踪是你的工作。
  • 您是否尝试将超时时间设置为时钟持续时间std::chrono::duration_cast&lt;my_clock::duration&gt;(seconds_duration(3))

标签: c++ linux macos c++11


【解决方案1】:

尝试将超时时间设置为时钟的持续时间:

auto planned_awake = my_clock::now() + 
                     std::chrono::duration_cast<my_clock::duration>(secon‌​ds_duration(3));

【讨论】:

  • 谢谢,这行得通!我之前尝试将其转换如下:“时间点计划唤醒 = my_clock::now() + std::chrono::duration_cast<:duration>(secon‌​ds_duration(3));”但这没有任何区别。使用 auto 关键字而不是 timepoint 正在起作用。但为什么呢?
  • 我不确定,但虽然操纵不同的持续时间可以正常工作并且会因缩小转换而失败,但 time_points 并不那么敏感。如果您使用ˋmy_clock::time_pointˋ,它将起作用。
猜你喜欢
  • 2021-02-01
  • 2012-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-03
  • 2019-04-10
  • 2019-05-24
  • 2016-07-15
相关资源
最近更新 更多