C ++非阻塞异步计时器

时间:2016-12-14 21:20:57

标签: c++ multithreading timer background

我已经阅读了很多关于此的帖子,但没有找到这个问题的答案。 我想创建一个在后台运行的计时器类,并在完成后执行某些操作。甚至我想要同时调用多个计时器,这些计时器是异步倒计时的。

我在搜索它的时候发现了这个课程,这看起来很有效,但在背景中却没有。我怎样才能将它改造成我想做的?

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()();
}

1 个答案:

答案 0 :(得分: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! ----------------