I would like to schedule tasks at different time intervals: at 0.1 sec, 0.9s .... 2s etc I use the clock() C++ function that returns the number of ticks since the beginning of the simulation and I convert the ticks number to seconds using CLOCKS_PER_SEC but I have noticed that the task isn't scheduled when the instant is a float, but when it's an integer it does. Here the portion of the code responsible for the scheduling:
float goal = (float) clock() / CLOCKS_PER_SEC + 0.4 ; // initially (float) clock() / CLOCKS_PER_SEC = 0 ;
if ((float) clock() / CLOCKS_PER_SEC == goal)
do stuff ;
In that case, it doesn't work, but when I schedule the task to be done in 3 seconds for instance it works. Is it a problem of precision??
If I was to implement some timer mechanism in C++, I would probably be using the std::chrono
namespace together with std::priority_queue
.
#include <functional>
#include <queue>
#include <chrono>
#include <sys/time.h> // for `time_t` and `struct timeval`
namespace events
{
struct event
{
typedef std::function<void()> callback_type;
typedef std::chrono::time_point<std::chrono::system_clock> time_type;
event(const callback_type &cb, const time_type &when)
: callback_(cb), when_(when)
{ }
void operator()() const
{ callback_(); }
callback_type callback_;
time_type when_;
};
struct event_less : public std::less<event>
{
bool operator()(const event &e1, const event &e2) const
{
return (e2.when_ < e1.when_);
}
};
std::priority_queue<event, std::vector<event>, event_less> event_queue;
void add(const event::callback_type &cb, const time_t &when)
{
auto real_when = std::chrono::system_clock::from_time_t(when);
event_queue.emplace(cb, real_when);
}
void add(const event::callback_type &cb, const timeval &when)
{
auto real_when = std::chrono::system_clock::from_time_t(when.tv_sec) +
std::chrono::microseconds(when.tv_usec);
event_queue.emplace(cb, real_when);
}
void add(const event::callback_type &cb,
const std::chrono::time_point<std::chrono::system_clock> &when)
{
event_queue.emplace(cb, when);
}
void timer()
{
event::time_type now = std::chrono::system_clock::now();
while (!event_queue.empty() &&
(event_queue.top().when_ < now))
{
event_queue.top()();
event_queue.pop();
}
}
}
To use, simply add events using events::add
, and call events::timer
a few times every second.
Example:
void foo()
{
std::cout << "hello from foo\n";
}
void done()
{
std::cout << "Done!\n";
}
struct bar
{
void hello()
{ std::cout << "Hello from bar::hello\n"; }
};
auto now = std::chrono::system_clock::now();
bar b;
events::add(foo, now + std::chrono::seconds(2));
events::add(std::bind(&bar::hello, b), now + std::chrono::seconds(4));
events::add(done, now + std::chrono::seconds(6));
while (true)
{
usleep(10000);
events::timer();
}
The above example will print:
hello from foo hello from bar::hello Done!
One line will be printed every two second. After "Done!"
the program will just loop forever, doing nothing.
Note that this program contains lots of C++11 functionality, but has been tested with GCC 4.4.5 and 4.7.1. VC++2010 unfortunately does not have the <chrono>
header, but the VC++2012RC apparently have it.
CLOCKS_PER_SEC is integer in your system. in other systems, it could be float too. put (float) near it too
The problem could be because of your floating point comparison. This can provide unexpected results. Please avoid this.
Refer this link
来源:https://stackoverflow.com/questions/11865460/issue-when-scheduling-tasks-using-clock-function