2017-12-07 5 views
1

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) 

그래서 시간 초과가 약간의 초 단위로 예정되어 있습니다. 나는 timeout timepoint를 가지고 뭔가를 엉망으로 만들고 있다고 생각하지만, 내가 뭘 잘못하고 있는지 알 수 없다.

관련성이있는 경우이 코드는 OSX에서 정상적으로 작동하지만 Linux (Ubuntu 16.04, gcc 5.4, "g ++ main.cc -std = C++ 11 -pthread"로 컴파일 됨)에서는 이상한 행동.

어떻게 작동시킬 수 있습니까?

+0

, 당신은 당신이 기다리고있는 것은 이미 일어나지도 않은 확인해야합니다. 그리고 기다리지 않기로 결정하기 전에 기다리고있는 것이 이미 일어 났는지 확인해야합니다. 조건 변수는 상태 비 저장이며 기다리고있는 것이 무엇인지 또는 그것이 발생했는지 알지 못합니다. 계속 추적하는 것이 당신의 일입니다. –

+0

타임 아웃을 시계 기간'std :: chrono :: duration_cast (seconds_duration (3))'에 캐스팅하려고 시도 했습니까? –

답변

0

는 시계의 시간에 타임 아웃을 던져보십시오 : 당신은 기다려야하기 전에

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

고맙습니다. 이전에 다음과 같이 캐스팅하려고했습니다 : "timepoint plans_awake = my_clock :: now() + std :: chrono :: duration_cast (secon ds_duration (3));" 하지만 아무런 차이가 없습니다. 대신 timepoint 대신 auto 키워드를 사용하는 것이 효과적입니다. 하지만 왜? – stavoltafunzia

+0

확실하지는 않지만 다른 기간을 조작해도 문제가 없지만 전환을 좁혀서 실패하더라도 time_point는 너무 민감하지 않습니다. 그것은 당신이 'amy_clock :: time_point'를 사용하면 작동 할 것입니다. –