2017-04-26 1 views
0

C++/stdlib에서 정기적으로 발생하는 타이머 기능을 설치하는 간단한 방법이 있습니까? 루프를 없애고 싶습니다.reoccurring 타이머 기능을 설치하는 방법은 무엇입니까?

using namespace std::chrono; // literal suffixes 
auto tNext = steady_clock::now(); 
while (<condition>) { 
    std::this_thread::sleep_until(tNext); 
    tNext = tNext + 100ms; 
    ... 

해당 함수는 자체 스레드에서 실행됩니다. 난 당신이 원하는 것을 추측하고있어

+1

프로그램이 다른 작업을 수행하는 동안 타이머가 비동기 적으로 작동하게 하시겠습니까? 그런 다음 내부 스레드를 시간 지정 프로세스에 넣어야합니다. –

+0

@JasonLang 물론 그 자체의 스레드 – towi

+0

'ping (100ms, callback)'행을 따라 뭔가를 원한다는 것을 의미합니까? –

답변

0

int i = 10; 
auto pred = [i]() mutable {return i--;}; 
auto print = []{cout << "." << endl;}; 

timer t{500ms}; 
t.push({print, pred}); //asynchronously prints '.' 10 times within 5s 

//do anything else 

가정 성능이 중요하지 않고 타이머가 종종 충분한 기능을 제공해야 다음, 업데이트되지 않습니다이다.

#include<functional> 
#include<vector> 
#include<thread> 
#include<utility> 
#include<chrono> 
#include<mutex> 
#include<atomic> 

class timer final 
{ 
public: 
    using microseconds = std::chrono::microseconds; 

    using predicate = std::function<bool()>; 
    using callback = std::function<void()>; 
    using job = std::pair<callback, predicate>; 

    explicit timer(microseconds t) : done{false}, period{t} 
    { 
     std::lock_guard<std::mutex> lck(mtx); 

     worker = std::thread([this]{ 
      auto t = std::chrono::steady_clock::now(); 
      while(!done.load()) 
      { 
       std::this_thread::sleep_until(t); 
       std::lock_guard<std::mutex> lck(mtx); 
       t += period; 
       for(auto it = jobs.begin(); it != jobs.end();) 
       { 
        if(it->second()) 
         it++->first(); 
        else 
         it = jobs.erase(it); 
       } 
      } 
     }); 
    } 

    ~timer() 
    { 
     done.store(true); 
     worker.join(); 
    } 

    void set_period(microseconds t) 
    { 
     std::lock_guard<std::mutex> lck(mtx); 
     period = t; 
    } 
    void push(const callback& c) 
    { 
     std::lock_guard<std::mutex> lck(mtx); 
     jobs.emplace_back(c, []{return true;}); 
    } 
    void push(const job& j) 
    { 
     std::lock_guard<std::mutex> lck(mtx); 
     jobs.push_back(j); 
    } 

private: 
    std::mutex mtx; 
    std::atomic_bool done; 
    std::thread worker; 

    std::vector<job> jobs; 
    microseconds period; 
}; 

timer 호출 이전에 주기적으로 callback들 기선을 제압 당했지만, predicatefalse로 평가하면, timer에서 callback을 삭제합니다. timer 개체는 자체 수명을 가지며 작업자 스레드는 그것이 살아있는 동안 만 살아갑니다.

timer에 복수의 job을 넣고 싶은 이유는 하나의 스레드 만 사용하여 함께 호출되고 서로 동기화되기 때문입니다.

는 타이머를> 10,000 회 초를 업데이트 할 계획하지 않는 한 mutex 걱정 <이 1ms의 기간이 있거나 매우 많은 시간이 소요 callback의이 없습니다.

+0

네, 그건 제가 생각한 것 이상의 아름다운 해결책입니다. 실제로는 매우 유용합니다. 작은 질문. 왜냐하면 원자력에 정통하지 않기 때문입니다. 'atomic_bool' 대신에'atomic_flag'을 사용할 수 있습니까? 모든 시스템에서 자물쇠가없는 유일한 원자로가 들립니다. – towi

+0

@ 토위 당신은 그것을 일하게 만들 수 있지만 조금 어색해집니다. 두 가지 사항을 기록해 두십시오. 첫째, 기본적으로 잠금 기능이 전혀 중요하지 않습니다. 둘째, 표준에 의해 보장되지 않더라도 실제로는 실제로 잠금이 없습니다. –

관련 문제