2016-12-14 9 views
1

これについて多くの記事を読んだことがありますが、この質問に対する答えは見つかりませんでした。 私は、バックグラウンドで動作するタイマークラスを作りたいと思っています。そして私は一度に複数のタイマーを呼び出すこともできますが、これは非同期的にカウントダウンされます。C++ノンブロッキング非同期タイマー

私はこのクラスを探していましたが、これは動作しているように見えますが、バックグランドでは見えませんでした。私はそれをどのように変えることができますか?

Timer.h:

#ifndef TIMER_H 
#define TIMER_H 

#include <thread> 
#include <chrono> 

class Timer 
{ 
public: 
    typedef std::chrono::milliseconds Interval; 
    typedef std::function<void(void)> Timeout; 

    Timer(const Timeout &timeout); 
    Timer(const Timeout &timeout, 
      const Interval &interval, 
      bool singleShot = true); 

    void start(bool multiThread = false); 
    void stop(); 

    bool running() const; 

    void setSingleShot(bool singleShot); 
    bool isSingleShot() const; 

    void setInterval(const Interval &interval); 
    const Interval &interval() const; 

    void setTimeout(const Timeout &timeout); 
    const Timeout &timeout() const; 

private: 
    std::thread _thread; 

    bool _running = false; 
    bool _isSingleShot = true; 

    Interval _interval = Interval(0); 
    Timeout _timeout = nullptr; 

    void _temporize(); 
    void _sleepThenTimeout(); 
}; 

#endif // TIMER_H 
enter code here 

Timer.cpp:

#include "Timer.h" 

Timer::Timer(const Timeout &timeout) 
    : _timeout(timeout) 
{ 
} 

Timer::Timer(const Timer::Timeout &timeout, 
      const Timer::Interval &interval, 
      bool singleShot) 
    : _isSingleShot(singleShot), 
     _interval(interval), 
     _timeout(timeout) 
{ 
} 

void Timer::start(bool multiThread) 
{ 
    if (this->running() == true) 
     return; 

    _running = true; 

    if (multiThread == true) { 
     _thread = std::thread(
        &Timer::_temporize, this); 
    } 
    else{ 
     this->_temporize(); 
    } 
} 

void Timer::stop() 
{ 
    _running = false; 
    _thread.join(); 
} 

bool Timer::running() const 
{ 
    return _running; 
} 

void Timer::setSingleShot(bool singleShot) 
{ 
    if (this->running() == true) 
     return; 

    _isSingleShot = singleShot; 
} 

bool Timer::isSingleShot() const 
{ 
    return _isSingleShot; 
} 

void Timer::setInterval(const Timer::Interval &interval) 
{ 
    if (this->running() == true) 
     return; 

    _interval = interval; 
} 

const Timer::Interval &Timer::interval() const 
{ 
    return _interval; 
} 

void Timer::setTimeout(const Timeout &timeout) 
{ 
    if (this->running() == true) 
     return; 

    _timeout = timeout; 
} 

const Timer::Timeout &Timer::timeout() const 
{ 
    return _timeout; 
} 

void Timer::_temporize() 
{ 
    if (_isSingleShot == true) { 
     this->_sleepThenTimeout(); 
    } 
    else { 
     while (this->running() == true) { 
      this->_sleepThenTimeout(); 
     } 
    } 
} 

void Timer::_sleepThenTimeout() 
{ 
    std::this_thread::sleep_for(_interval); 

    if (this->running() == true) 
     this->timeout()(); 
} 
+0

startメソッドでmultithreadパラメータを使用して、別のスレッドとして実行するよう指定していませんか? –

+0

「バックグラウンドで」とはどういう意味ですか? – immibis

+0

@immibis私はそれが非同期的に意味していると仮定しました。 –

答えて

1

次のクラスがカウントダウンする時と終了時に実行する関数のパラメータを取ります。

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

class Timer { 
public: 
    Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {} 
    ~Timer() { wait_thread.join(); } 

private: 
    void wait_then_call() 
    { 
     std::unique_lock<std::mutex> lck{mtx}; 
     for(int i{10}; i > 0; --i) { 
      std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << '\n'; 
      cv.wait_for(lck, time/10); 
     } 
     f(); 
    } 
    std::mutex mtx; 
    std::condition_variable cv{}; 
    std::chrono::milliseconds time; 
    std::function <void(void)> f; 
    std::thread wait_thread{[this]() {wait_then_call(); }}; 
}; 

int main() 
{ 
    auto f = []() {std::cout << "---------------- I waited to print! ----------------\n"; }; 
    Timer t1{3000,f}; 
    Timer t2{10'000,f}; 
    Timer t3{20'000,f}; 
    Timer t4{1000,f}; 
} 

生産数:

Thread Thread 43184 countdown at:  Thread 24004 countdown at:  10 
Thread 61592 countdown at:  10 
72408 countdown at:  10 
10 
Thread 24004 countdown at:  9 
Thread 24004 countdown at:  8 
Thread 72408 countdown at:  Thread 24004 countdown at:  9 
7 
Thread 24004 countdown at:  6 
Thread 24004 countdown at:  5 
Thread 72408 countdown at:  8 
Thread 24004 countdown at:  4 
Thread 24004 countdown at:  3 
Thread 24004 countdown at:  2 
Thread 72408 countdown at:  7 
Thread 24004 countdown at:  1 
Thread 61592 countdown at:  9 
---------------- I waited to print! ---------------- 
Thread 72408 countdown at:  6 
Thread 72408 countdown at:  5 
Thread 72408 countdown at:  4 
Thread 43184 countdown at:  9 
Thread 61592 countdown at:  8 
Thread 72408 countdown at:  3 
Thread 72408 countdown at:  2 
Thread 72408 countdown at:  1 
Thread 61592 countdown at:  7 
---------------- I waited to print! ---------------- 
Thread 43184 countdown at:  8 
Thread 61592 countdown at:  6 
Thread 61592 countdown at:  5 
Thread 43184 countdown at:  7 
Thread 61592 countdown at:  4 
Thread 61592 countdown at:  3 
Thread 43184 countdown at:  6 
Thread 61592 countdown at:  2 
Thread 61592 countdown at:  1 
Thread 43184 countdown at:  5 
---------------- I waited to print! ---------------- 
Thread 43184 countdown at:  4 
Thread 43184 countdown at:  3 
Thread 43184 countdown at:  2 
Thread 43184 countdown at:  1 
---------------- I waited to print! ----------------