setting the execution rate of while loop in a C++ code for real time synchronization - c++

I am doing a real_time simulation using a .cpp source code. I have to take a sample every 0.2 seconds (200 ms) ... There is a while loop that takes a sample every time step... I want to synchronize the execution of this while loop to get a sample every (200 ms) ... How should I modify the while loop ?
while (1){
// get a sample every 200 ms
}

Simple and accurate solution with std::this_thread::sleep_until:
#include "date.h"
#include <chrono>
#include <iostream>
#include <thread>
int
main()
{
using namespace std::chrono;
using namespace date;
auto next = steady_clock::now();
auto prev = next - 200ms;
while (true)
{
// do stuff
auto now = steady_clock::now();
std::cout << round<milliseconds>(now - prev) << '\n';
prev = now;
// delay until time to iterate again
next += 200ms;
std::this_thread::sleep_until(next);
}
}
"date.h" isn't needed for the delay part. It is there to provide the round<duration> function (which is now in C++17), and to make it easier to print out durations. This is all under "do stuff", and doesn't matter for the loop delay.
Just get a chrono::time_point, add your delay to it, and sleep until that time_point. Your loop will on average stay true to your delay, as long as your "stuff" takes less time than your delay. No other thread needed. No timer needed. Just <chrono> and sleep_until.
This example just output for me:
200ms
205ms
200ms
195ms
205ms
198ms
202ms
199ms
196ms
203ms
...

what you are asking is tricky, unless you are using a real-time operating system.
However, Boost has a library that supports what you want. (There is, however, no guarantee that you are going to be called exactly every 200ms.
The Boost ASIO library is probably what you are looking for though, here is code from their tutorial:
//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello, world!\n";
return 0;
}
link is here: link to boost asio.
You could take this code, and re-arrange it like this
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
while(1)
{
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
// process your IO here - not sure how long your IO takes, so you may need to adjust your timer
t.wait();
}
return 0;
}
There is also a tutorial for handling the IO asynchronously on the next page(s).

The offered answers show you that there are tools available in Boost to help you accomplish this. My late offering illustrates how to use setitimer(), which is a POSIX facility for iterative timers.
You basically need a change like this:
while (1){
// wait until 200 ms boundary
// get a sample
}
With an iterative timer, the fired signal would interrupt any blocked signal call. So, you could just block on something forever. select will do fine for that:
while (1){
int select_result = select(0, 0, 0, 0, 0);
assert(select_result < 0 && errno == EINTR);
// get a sample
}
To establish an interval timer for every 200 ms, use setitimer(), passing in an appropriate interval. In the code below, we set an interval for 200 ms, where the first one fires 150 ms from now.
struct itimerval it = { { 0, 200000 }, { 0, 150000 } };
if (setitimer(ITIMER_REAL, &it, 0) != 0) {
perror("setitimer");
exit(EXIT_FAILURE);
}
Now, you just need to install a signal handler for SIGALRM that does nothing, and the code is complete.
You can follow the link to see the completed example.
If it is possible for multiple signals to be fired during the program execution, then instead of relying on the interrupted system call, it is better to block on something that the SIGALRM handler can wake up in a deterministic way. One possibility is to have the while loop block on read of the read end of a pipe. The signal handler can then write to the write end of that pipe.
void sigalarm_handler (int)
{
if (write(alarm_pipe[1], "", 1) != 1) {
char msg[] = "write: failed from sigalarm_handler\n";
write(2, msg, sizeof(msg)-1);
abort();
}
}
Follow the link to see the completed example.

#include <thread>
#include <chrono>
#include <iostream>
int main() {
std::thread timer_thread;
while (true) {
timer_thread = std::thread([](){
std::this_thread::sleep_for (std::chrono::seconds(1));
});
// do stuff
std::cout << "Hello World!" << std::endl;
// waits until thread has "slept"
timer_thread.join();
// will loop every second unless the stuff takes longer than that.
}
return 0;
}

To get absolute percision will be nearly impossible - maybe in embedded systems. However, if you require only an approximate frequency, you can get pretty decent performance with a chrono library such as std::chrono (c++11) or boost::chrono. Like so:
while (1){
system_clock::time_point now = system_clock::now();
auto duration = now.time_since_epoch();
auto start_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
//run sample
now = system_clock::now();
duration = now.time_since_epoch();
auto end_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
auto sleep_for = max(0, 200 - (end_millis - start_millis ));
std::this_thread::sleep_for( sleep_for );
}

Related

How to get local hour efficiently?

I'm developing a service. Currently I need to get local hour for every request, since it involves system call, it costs too much.
In my case, some deviation like 200ms is OK for me.
So what's the best way to maintain a variable storing local_hour, and update it every 200ms?
static int32_t GetLocalHour() {
time_t t = std::time(nullptr);
if (t == -1) { return -1; }
struct tm *time_info_ptr = localtime(&t);
return (nullptr != time_info_ptr) ? time_info_ptr->tm_hour : -1;
}
If you want your main thread to spend as little time as possible on getting the current hour you can start a background thread to do all the heavy lifting.
For all things time use std::chrono types.
Here is the example, which uses quite a few (very useful) multithreading building blocks from C++.
#include <chrono>
#include <future>
#include <condition_variable>
#include <mutex>
#include <atomic>
#include <iostream>
// building blocks
// std::future/std::async, to start a loop/function on a seperate thread
// std::atomic, to be able to read/write threadsafely from a variable
// std::chrono, for all things time
// std::condition_variable, for communicating between threads. Basicall a signal that only signals that something has changed that might be interesting
// lambda functions : anonymous functions that are useful in this case for starting the asynchronous calls and to setup predicates (functions returning a bool)
// std::mutex : threadsafe access to a bit of code
// std::unique_lock : to automatically unlock a mutex when code goes out of scope (also needed for condition_variable)
// helper to convert time to start of day
using days_t = std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24> >::type>;
// class that has an asynchronously running loop that updates two variables (threadsafe)
// m_hours and m_seconds (m_seconds so output is a bit more interesting)
class time_keeper_t
{
public:
time_keeper_t() :
m_delay{ std::chrono::milliseconds(200) }, // update loop period
m_future{ std::async(std::launch::async,[this] {update_time_loop(); }) } // start update loop
{
// wait until asynchronous loop has started
std::unique_lock<std::mutex> lock{ m_mtx };
// wait until the asynchronous loop has started.
// this can take a bit of time since OS needs to schedule a thread for that
m_cv.wait(lock, [this] {return m_started; });
}
~time_keeper_t()
{
// threadsafe stopping of the mainloop
// to avoid problems that the thread is still running but the object
// with members is deleted.
{
std::unique_lock<std::mutex> lock{ m_mtx };
m_stop = true;
m_cv.notify_all(); // this will wakeup the loop and stop
}
// future.get will wait until the loop also has finished
// this ensures no member variables will be accessed
// by the loop thread and it is safe to fully destroy this instance
m_future.get();
}
// inline to avoid extra calls
inline int hours() const
{
return m_hours;
}
// inline to avoid extra calls
inline int seconds() const
{
return m_seconds;
}
private:
void update_time()
{
m_now = std::chrono::steady_clock::now();
std::chrono::steady_clock::duration tp = m_now.time_since_epoch();
// calculate back till start of day
days_t days = duration_cast<days_t>(tp);
tp -= days;
// calculate hours since start of day
auto hours = std::chrono::duration_cast<std::chrono::hours>(tp);
tp -= hours;
m_hours = hours.count();
// seconds since start of last hour
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(tp);
m_seconds = seconds.count() % 60;
}
void update_time_loop()
{
std::unique_lock<std::mutex> lock{ m_mtx };
update_time();
// loop has started and has initialized all things time with values
m_started = true;
m_cv.notify_all();
// stop condition for the main loop, put in a predicate lambda
auto stop_condition = [this]()
{
return m_stop;
};
while (!m_stop)
{
// wait until m_cv is signaled or m_delay timed out
// a condition variable allows instant response and thus
// is better then just having a sleep here.
// (imagine a delay of seconds, that would also mean stopping could
// take seconds, this is faster)
m_cv.wait_for(lock, m_delay, stop_condition);
if (!m_stop) update_time();
}
}
std::atomic<int> m_hours;
std::atomic<int> m_seconds;
std::mutex m_mtx;
std::condition_variable m_cv;
bool m_started{ false };
bool m_stop{ false };
std::chrono::steady_clock::time_point m_now;
std::chrono::steady_clock::duration m_delay;
std::future<void> m_future;
};
int main()
{
time_keeper_t time_keeper;
// the mainloop now just can ask the time_keeper for seconds
// or in your case hours. The only time needed is the time
// to return an int (atomic) instead of having to make a full
// api call to get the time.
for (std::size_t n = 0; n < 30; ++n)
{
std::cout << "seconds now = " << time_keeper.seconds() << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
You don't need to query local time for every request because hour doesn't change every 200ms. Just update the local hour variable every hour
The most correct solution would be registering to a timer event like scheduled task on Windows or cronjobs on Linux that runs at the start of every hour. Alternatively create a timer that runs every hour and update the variable
The timer creation depends on the platform, for example on Windows use SetTimer, on Linux use timer_create. Here's a very simple solution using boost::asio which assumes that you run on the exact hour. You'll need to make some modification to allow it to run at any time, for example by creating a one-shot timer or by sleeping until the next hour
#include <chrono>
using namespace std::chrono_literals;
int32_t get_local_hour()
{
time_t t = std::time(nullptr);
if (t == -1) { return -1; }
struct tm *time_info_ptr = localtime(&t);
return (nullptr != time_info_ptr) ? time_info_ptr->tm_hour : -1;
}
static int32_t local_hour = get_local_hour();
bool running = true;
// Timer callback body, called every hour
void update_local_hour(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t)
{
while (running)
{
t->expires_at(t->expires_at() + boost::posix_time::hour(1));
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
local_hour = get_local_hour();
}
}
int main()
{
boost::asio::io_service io;
// Timer that runs every hour and update the local_hour variable
boost::asio::deadline_timer t(io, boost::posix_time::hour(1));
t.async_wait(boost::bind(update_local_hour,
boost::asio::placeholders::error, &t));
running = true;
io.run();
std::this_thread::sleep_for(3h);
running = false; // stop the timer
}
Now just use local_hour directly instead of GetLocalHour()

What is the equivalent of Qtimer in C++ using std or boost libraries?

I have to perform some task every 5 seconds till the program exits. I don't want to use a thread here.
In QT I could do like this
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
but how do I do this in c++ using std or boost libraries?
Thank you
I have to assume that, by "I don't want to use a thread", you mean you don't want to create threads in your own code every time you need a timer. That's because doing it without threads is actually quite hard.
Assuming C++11, you can actually do this with just the core language (no Boost or any other stuff needed) and using a separate class handling the threading so that all you need in your own code is something like (for example, harassing your ex partner with spam emails, a rather dubious use case):
Periodic spamEx(std::chrono::seconds(60), SendEmaiToEx);
The following complete program, compiled with g++ -std=c++11 -o periodic periodic.cpp -lpthread will run a periodic callback function every second for five seconds(a):
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
// Not needed if you take couts out of Periodic class.
#include <iostream>
class Periodic {
public:
explicit Periodic(
const std::chrono::milliseconds &period,
const std::function<void ()> &func
)
: m_period(period)
, m_func(func)
, m_inFlight(true)
{
std::cout << "Constructing periodic" << std::endl;
m_thread = std::thread([this] {
while (m_inFlight) {
std::this_thread::sleep_for(m_period);
if (m _inFlight) {
m_func();
}
}
});
}
~Periodic() {
std::cout << "Destructed periodic" << std::endl;
m_inFlight = false;
m_thread.join();
std::cout << "Destructed periodic" << std::endl;
}
private:
std::chrono::milliseconds m_period;
std::function<void ()> m_func;
std::atomic<bool> m_inFlight;
std::thread m_thread;
};
// This is a test driver, the "meat" is above this.
#include <iostream>
void callback() {
static int counter = 0;
std::cout << "Callback " << ++counter << std::endl;
}
int main() {
std::cout << "Starting main" << std::endl;
Periodic p(std::chrono::seconds(1), callback);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Ending main" << std::endl;
}
When you create an instance of Periodic, it saves the relevant information and starts a thread to do the work. The thread (a lambda) is simply a loop which first delays for the period then calls your function. It continues to do this until the destructor indicates it should stop.
The output is, as expected:
Starting main
Constructing periodic
Callback 1
Callback 2
Callback 3
Callback 4
Ending main
Destructed periodic
(a) Note that the time given above is actually the time from the end of one callback to start of the next, not the time from start to start (what I would call true cycle time). Provided your callback is sufficiently quick compared to the period, the difference will hopefully be unnoticable.
In addition, the thread does this delay no matter what, so the destructor may be delayed for up to a full period before returning.
If you do require a start-to-start period and fast clean-up, you can use the following thread instead. It does true start-to-start timing by working out the duration of the callback and only delaying by the rest of the period (or not delaying at all if the callback used the entire period).
It also uses a smaller sleep so that clean-up is fast. The thread function would be:
m_thread = std::thread([this] {
// Ensure we wait the initial period, then start loop.
auto lastCallback = std::chrono::steady_clock::now();
while (m_inFlight) {
// Small delay, then get current time.
std::this_thread::sleep_for(std::chrono::milliseconds(100));
auto timeNow = std::chrono::steady_clock::now();
// Only callback if still active and current period has expired.
if (m_inFlight && timeNow - lastCallback >= m_period) {
// Start new period and call callback.
lastCallback = timeNow;
m_func();
}
}
});
Be aware that, if your callback takes longer than the period, you will basically be calling it almost continuously (there'll be a 100ms gap at least).
You realize that QTimer does use a thread - or polls the timer in the main event loop. You can do the same. The conceptual problem you're likely having is that you don't have a UI and therefore, probably didn't create an event loop.
Here's the simplest way to leverage Boost Asio to have an event loop:
Live On Coliru
#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <functional>
#include <chrono>
#include <iostream>
using namespace std::chrono_literals;
using boost::system::error_code;
namespace ba = boost::asio;
int main() {
ba::io_service svc; // prefer io_context in recent boost versions
ba::high_resolution_timer timer{svc};
std::function<void()> resume;
resume = [&] {
timer.expires_from_now(50ms); // just for demo, don't wait 5s but 50ms
timer.async_wait([=,&timer](error_code ec) {
std::cout << "Timer: " << ec.message() << "\n";
if (!ec)
resume();
});
};
resume();
svc.run_for(200ms); // probably getting 3 or 4 successful callbacks
timer.cancel();
svc.run(); // graceful shutdown
}
Prints:
Timer: Success
Timer: Success
Timer: Success
Timer: Success
Timer: Operation canceled
That may not make too much sense depending on the rest of your application. In such cases, you can do the same but use a separate thread (yes) to run that event loop.

Calling a function every 1 second (precisely)

I am working on a simple game simulation program in C++, there's a function called update() that updates the current state of the game, it has to be called every 1 second precisely. If I use a loop like this:
while(//some condition) {
update();
Sleep(1000);
}
Then the function will not be called every 1 second, instead, every (1 + execution time of update () ).
I read about various solutions like async functions, multithreading, or calculating the function's execution time using std::chrono and subtracting it from the 1000ms parameter to sleep. Some of those were too complicated for my simple case, and others seemed unsafe to use if I don't understand them really well.
Can anyone tell me what would be a suitable solution to my requirement?
Thanks in advance.
Instead of sleeping for a duration, you need to sleep until a time point. For example, if your first update is at precisely 2:00:00.000, your future updates should come as closely as possible to 2:00:01.000, 2:00:02.000, etc.
To achieve this you can dedicate a thread to updating, and after the update, goes to sleep until the next time to do a scheduled update. chrono::system_clock::time_point and this_thread::sleep_until are your tools to do this.
For example:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class UpdateManager
{
public:
explicit UpdateManager() = default;
private:
static std::atomic<int> now_;
static std::atomic<bool> stop_;
struct update_thread
: private std::thread
{
~update_thread();
update_thread(update_thread&&) = default;
using std::thread::thread;
};
public:
static update_thread start();
};
void update();
// source
std::atomic<int> UpdateManager::now_{0};
std::atomic<bool> UpdateManager::stop_{false};
UpdateManager::update_thread::~update_thread()
{
if (joinable())
{
stop_ = true;
join();
}
}
UpdateManager::update_thread
UpdateManager::start()
{
return update_thread{[]
{
using namespace std;
using namespace std::chrono;
auto next = system_clock::now() + 1s;
while (!stop_)
{
update();
this_thread::sleep_until(next);
next += 1s;
}
}};
}
#include "date/date.h"
void
update()
{
using namespace date;
using namespace std;
using namespace std::chrono;
cerr << system_clock::now() << '\n';
}
// demo
int
main()
{
auto t = UpdateManager::start();
using namespace std;
this_thread::sleep_for(10s);
}
Just for demo purposes (not necessary for the logic), I'm using Howard Hinnant's, free, open-source date/time library to print the current time (UTC) to microsecond precision in order to illustrate the stability of this technique. A sample output of this program is:
2018-05-02 15:14:25.634809
2018-05-02 15:14:26.637934
2018-05-02 15:14:27.636629
2018-05-02 15:14:28.637947
2018-05-02 15:14:29.638413
2018-05-02 15:14:30.639437
2018-05-02 15:14:31.637217
2018-05-02 15:14:32.637895
2018-05-02 15:14:33.637749
2018-05-02 15:14:34.639084
You can avoid using chrono for this simpler option instead. However, if you want μs-ns accuracy, I highly suggest using chrono.
#include <ctime>
while(//some condition) {
std::clock_t start = std::clock();
update();
std::clock_t end = std::clock();
Sleep(1000 - (end - start)/CLOCKS_PER_SEC * 1000);
}
The best way to ensure that something happens at the correct time is to use the this_thread::sleep_until() in the while loop, as a few others have recommended.
I like to make sure that my loop starts at the bottom of the second so calculated next_full_second time point using chrono time_since_epoch
interval variable can be set to seconds or milliseconds. Used open source date library by HowardHinnant to print out nice time values.
#include <chrono>
#include <iostream>
#include <thread>
#include "date/date.h"
using namespace date;
using namespace std;
using namespace std::chrono;
int main()
{
system_clock::time_point now = system_clock::now();
auto s = duration_cast<seconds>(now.time_since_epoch());
system_clock::time_point next_full_second = system_clock::time_point(++s);
auto interval = seconds(1); // or milliseconds(500) or whatever
auto wait_until = next_full_second;
while (1)
{
this_thread::sleep_until(wait_until);
cout << system_clock::now() << endl;
// do something
wait_until += interval;
}
return 0;
}
See this pseudo code. If every process ( which may take more than 1sec ) is done in separate threads asynchronously, you can sleep exactly 1 sec before next loop as desired.
void MainGameLoop(bool& running)
{
while (running)
{
AnimateSpritesAsync();
AnimateBulletsAsync();
CheckCollisionAsync();
CheckWinConditionsAsync();
WaitPreciselyOneSecond();
}
}
For example your update function will look like this:
void update(); //your update
void UpdateAsync() // the async update
{
std::thread([]() { update(); }).detach();
}
Now you can:
void MainGameLoop(bool& running)
{
while (running)
{
UpdateAsync();
Sleep(1000); // i won't recommend Sleep tho
}
}

Calling functions at timed intervals using threads

I'm building a simulator to test student code for a very simple robot. I need to run two functions(to update robot sensors and robot position) on separate threads at regular time intervals. My current implementation is highly processor inefficient because it has a thread dedicated to simply incrementing numbers to keep track of the position in the code. My recent theory is that I may be able to use sleep to give the time delay between updating value of the sensor and robot position. My first question is: is this efficient? Second: Is there any way to do a simple thing but measure clock cycles instead of seconds?
Putting a thread to sleep by waiting on a mutex-like object is generally efficient. A common pattern involves waiting on a mutex with a timeout. When the timeout is reached, the interval is up. When the mutex is releaed, it is the signal for the thread to terminate.
Pseudocode:
void threadMethod() {
for(;;) {
bool signalled = this->mutex.wait(1000);
if(signalled) {
break; // Signalled, owners wants us to terminate
}
// Timeout, meaning our wait time is up
doPeriodicAction();
}
}
void start() {
this->mutex.enter();
this->thread.start(threadMethod);
}
void stop() {
this->mutex.leave();
this->thread.join();
}
On Windows systems, timeouts are generally specified in milliseconds and are accurate to roughly within 16 milliseconds (timeBeginPeriod() may be able to improve this). I do not know of a CPU cycle-triggered synchronization primitive. There are lightweight mutexes called "critical sections" that spin the CPU for a few thousand cycles before delegating to the OS thread scheduler. Within this time they are fairly accurate.
On Linux systems the accuracy may be a bit higher (high frequency timer or tickless kernel) and in addition to mutexes, there are "futexes" (fast mutex) which are similar to Windows' critical sections.
I'm not sure I grasped what you're trying to achieve, but if you want to test student code, you might want to use a virtual clock and control the passing of time yourself. For example by calling a processInputs() and a decideMovements() method that the students have to provide. After each call, 1 time slot is up.
This C++11 code uses std::chrono::high_resolution_clock to measure subsecond timing, and std::thread to run three threads. The std::this_thread::sleep_for() function is used to sleep for a specified time.
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
void seconds()
{
using namespace std::chrono;
high_resolution_clock::time_point t1, t2;
for (unsigned i=0; i<10; ++i) {
std::cout << i << "\n";
t1 = high_resolution_clock::now();
std::this_thread::sleep_for(std::chrono::seconds(1));
t2 = high_resolution_clock::now();
duration<double> elapsed = duration_cast<duration<double> >(t2-t1);
std::cout << "\t( " << elapsed.count() << " seconds )\n";
}
}
int main()
{
std::vector<std::thread> t;
t.push_back(std::thread{[](){
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "awoke after 3\n"; }});
t.push_back(std::thread{[](){
std::this_thread::sleep_for(std::chrono::seconds(7));
std::cout << "awoke after 7\n"; }});
t.push_back(std::thread{seconds});
for (auto &thr : t)
thr.join();
}
It's hard to know whether this meets your needs because there are a lot of details missing from the question. Under Linux, compile with:
g++ -Wall -Wextra -pedantic -std=c++11 timers.cpp -o timers -lpthread
Output on my machine:
0
( 1.00014 seconds)
1
( 1.00014 seconds)
2
awoke after 3
( 1.00009 seconds)
3
( 1.00015 seconds)
4
( 1.00011 seconds)
5
( 1.00013 seconds)
6
awoke after 7
( 1.0001 seconds)
7
( 1.00015 seconds)
8
( 1.00014 seconds)
9
( 1.00013 seconds)
Other C++11 standard features that may be of interest include timed_mutex and promise/future.
Yes your theory is correct. You can use sleep to put some delay between execution of a function by thread. Efficiency depends on how wide you can choose that delay to get desired result. You have to explain details of your implementation. For e.g we don't know whether two threads are dependent ( in that case you have to take care of synchronization which would blow up some cycles ).
Here's the one way to do it. I'm using C++11, thread, atomics and high precision clock. The scheduler will callback a function that takes dt seconds which is time elapsed since last call. The loop can be stopped by calling stop() method of if callback function returns false.
Scheduler code
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include <system_error>
class ScheduledExecutor {
public:
ScheduledExecutor()
{}
ScheduledExecutor(const std::function<bool(double)>& callback, double period)
{
initialize(callback, period);
}
void initialize(const std::function<bool(double)>& callback, double period)
{
callback_ = callback;
period_ = period;
keep_running_ = false;
}
void start()
{
keep_running_ = true;
sleep_time_sum_ = 0;
period_count_ = 0;
th_ = std::thread(&ScheduledExecutor::executorLoop, this);
}
void stop()
{
keep_running_ = false;
try {
th_.join();
}
catch(const std::system_error& /* e */)
{ }
}
double getSleepTimeAvg()
{
//TODO: make this function thread safe by using atomic types
//right now this is not implemented for performance and that
//return of this function is purely informational/debugging purposes
return sleep_time_sum_ / period_count_;
}
unsigned long getPeriodCount()
{
return period_count_;
}
private:
typedef std::chrono::high_resolution_clock clock;
template <typename T>
using duration = std::chrono::duration<T>;
void executorLoop()
{
clock::time_point call_end = clock::now();
while (keep_running_) {
clock::time_point call_start = clock::now();
duration<double> since_last_call = call_start - call_end;
if (period_count_ > 0 && !callback_(since_last_call.count()))
break;
call_end = clock::now();
duration<double> call_duration = call_end - call_start;
double sleep_for = period_ - call_duration.count();
sleep_time_sum_ += sleep_for;
++period_count_;
if (sleep_for > MinSleepTime)
std::this_thread::sleep_for(std::chrono::duration<double>(sleep_for));
}
}
private:
double period_;
std::thread th_;
std::function<bool(double)> callback_;
std::atomic_bool keep_running_;
static constexpr double MinSleepTime = 1E-9;
double sleep_time_sum_;
unsigned long period_count_;
};
Example usage
bool worldUpdator(World& w, double dt)
{
w.update(dt);
return true;
}
void main() {
//create world for your simulator
World w(...);
//start scheduler loop for every 2ms calls
ScheduledExecutor exec;
exec.initialize(
std::bind(worldUpdator, std::ref(w), std::placeholders::_1),
2E-3);
exec.start();
//main thread just checks on the results every now and then
while (true) {
if (exec.getPeriodCount() % 10000 == 0) {
std::cout << exec.getSleepTimeAvg() << std::endl;
}
}
}
There are also other, related questions on SO.

Timeout in C++ using Boost datetime

How to implement a timeout while loop in C++ using boost::datetime?
something like:
#define TIMEOUT 12
while(some_boost_datetime_expression(TIMEOUT))
{
do_something(); // do it until timeout expires
}
// timeout expired
Use Boost::deadline_timer for timeouts. Constant check of value in loop is overkill for CPU.
You'll first want to mark the time you start, then calculate the difference between the current time and the time you started. No built-in boost datetime expression will work exactly like you describe. In boost datetime terminology: http://www.boost.org/doc/libs/1_51_0/doc/html/date_time.html the duration of your timeout is a "time duration", and the point you start is a "time point".
Suppose you want to be accurate to within a second, and have a 4 minute 2 second interval.
using namespace boost::posix_time;
ptime start = second_clock::local_time();
gives you a time point to start your timing
ptime end = start + minutes(4)+seconds(2);
gives you a point in time 4 minutes and 2 seconds from now.
And then
( second_clock::local_time() < end )
is true if and only if the current time is before the end time.
(Disclaimer: this is not based off actually writing any boost datetime code before, but just reading the docs and example code over at the boost website.)
You can just check the time difference:
boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
while((boost::posix_time::microsec_clock::local_time() - now) < boost::posix_time::milliseconds(TIMEOUT ) )
{
// do something
}
But instead of doing something like that you might rethink your design.
This can easily be done with boost.Asio. Start a deadline_timer as one async process. It cancels the event loop when it expires. Keep posting your work to the same event loop till it is running. A working solution:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class timed_job
{
public:
timed_job( int timeout ) :
timer_( io_service_, boost::posix_time::seconds( timeout ) ) // Deadline timer
{
}
void start()
{
// Start timer
timer_.async_wait
(
boost::bind
(
&timed_job::stop, this
)
);
// Post your work
io_service_.post
(
boost::bind
(
&timed_job::do_work, this
)
);
io_service_.run();
std::cout << "stopped." << std::endl;
}
private:
void stop()
{
std::cout << "call stop..." << std::endl;
io_service_.stop();
}
void do_work ()
{
std::cout << "running..." << std::endl;
// Keep posting the work.
io_service_.post
(
boost::bind
(
&timed_job::do_work, this
)
);
}
private:
boost::asio::io_service io_service_;
boost::asio::deadline_timer timer_;
};
int main()
{
timed_job job( 5 );
job.start();
return 0;
}