问题
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.
回答1:
I'm guessing what you want is this
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
calls previously pushed callback
s 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.
The reason you would want to have multiple job
s in a single timer
is so that they would be called together, using only one thread and be in sync with each other.
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 callback
s.
来源:https://stackoverflow.com/questions/43632280/how-to-install-a-reoccurring-timer-function