如何安装定期计时器功能? [英] How to install a reoccurring timer function?

查看:97
本文介绍了如何安装定期计时器功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种简单的方法来使用C ++/stdlib安装定期发生的计时器功能?我想摆脱循环:

Is there a simple way to install a regularly occurring timer function with C++/stdlib? I would like to get rid of the loop:

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

该函数将在其自己的线程中运行.

That function will run in its own thread.

推荐答案

我猜这是你想要的

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

假设性能不是很关键并且计时器不经常更新,则以下内容应提供足够的功能.

Assuming performance is not critical and the timer is not often updated, the following should provide ample functionality.

#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,并且当predicate评估为false时,将从timer中删除callback. timer对象具有其自己的生存期,并且其工作线程仅在存在时才存在.

timer calls previously pushed callbacks periodically, and when predicate evaluates to false, deletes the callback from the timer. The timer object has its own lifetime and its worker thread will only live as long as it is alive.

您希望在单个timer中包含多个job的原因是,它们可以仅使用一个线程一起调用,并且彼此同步.

The reason you would want to have multiple jobs in a single timer is so that they would be called together, using only one thread and be in sync with each other.

不要担心mutex,除非您打算每秒更新计时器> 10,000次,周期<1ms或非常耗时的callback.

Don't worry about the mutex unless you are planning to update the timer >10,000 times a second, have a period of <1ms or have very time-consuming callbacks.

这篇关于如何安装定期计时器功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆