私はC++でスレッドプールを作成しようとしています。コードはOSXでは正常に動作しますが、Linuxでは奇妙な動作が発生しています。 少しのデバッグの後、問題がstd :: condition_variable :: wait_untilの呼び出しによって間違った方法で実行されているに違いないことがわかりました。C++ 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;
}
は、しかし、時々私は出力として得る:コード付き
私はループが3秒ごとにループされることを期待を下回る
<X> wait until <X+3>
predicate called
(...hangs here for a long time)
(Xは数字です)、タイムアウトは3秒後に予定されていないようです。場合によっては代わりに、私は得る:
<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)
これはタイムアウトがわずかな秒数の後に予定されているようです。私はタイムアウトのタイムポイントで何かを台無しにしていると思うが、私が間違っていることを理解できない。
このコードは、Linux(Ubuntu 16.04、gcc 5.4、 "g ++ main.cc -std = C++ 11 -pthread"でコンパイルされている)の間にOSXでうまく動作します。奇妙な行動。
どうすれば動作させることができますか?あなたの時計の期間に、あなたのタイムアウトをキャストする
あなたが待つ前に、あなたが待っているものはまだ起きていないことを確認する必要があります。待つことを決断する前に、あなたが待っていることがすでに起こっていることを確認する必要があります。条件変数はステートレスであり、あなたが何を待っているのか、それが起こったのかどうかは分かりません。それはあなたの仕事を追跡することです。 –
あなたのタイムアウトをあなたの時計の持続時間にキャストしようとしましたか?:: chrono :: duration_cast(seconds_duration(3)) ' –