I have written a thread in Qt that does lot of things (calculations, data sampling, ...).
This thread has to be run in an interval of 1000ms.
The allowed error with the timer is about 5ms.
I have changed the priority of the thread to QThread::HighPriority but the thread runs in interval about to 1060ms-1100ms.
How can I make the interval more precise? (I have subclassed QThread and used msleep(interval) in the run() method).
You have coded your thread's run() method essentially as:
void MyThread::run() {
forever {
doSomething();
msleep(1000);
}
}
There are several problems:
doSomething() doesn't take zero amount of time. At the minimum, you'd need to time how long doSomething() takes and sleep that much shorter than 1000ms.
Both doSomething() and msleep() can take a variable amount of time, since your thread is never guaranteed not to be preempted, nor is it guaranteed to immediately start running once it's made runnable by the sleep expiring. Thus you need to keep track of time absolutely, not relatively to the start of doSomething().
You're using a generic sleep function without possibly leveraging better APIs that the underlying platform might offer.
A reasonably correct way to go about it would be expressed using this pseudocode:
const qint64 kInterval = 1000;
qint64 mtime = QDateTime::currentMSecsSinceEpoch();
forever {
doSomething();
mtime += kInterval;
qint64 sleepFor = mtime - QDateTime::currentMSecsSinceEpoch();
if (sleepFor < 0) {
// We got preempted for too long - for all we know, the system could
// have even gotten suspended (lid close on a laptop).
// Note: We should avoid the implementation-defined behavior of
// modulus (%) for negative values.
sleepFor = kInterval - ((-sleepFor) % kInterval);
}
OS_Precise_Wait_ms(sleepFor); // use the appropriate API on given platform
}
As luck would have it, Qt provides an API that does all this for you: the timers. They are a source of reasonably behaved periodic "ticks". Most naive re-implementations of this functionality are likely to get it wrong in one way or another, since it's not as simple as it looks.
Here is how you can reorganize the code:
class Worker : public QObject {
QBasicTimer m_timer;
void doSomething() {
// do the work
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) {
QObject::timerEvent(ev);
return;
}
doSomething();
}
public:
Worker(QObject * parent = 0) : QObject(parent) {
m_timer.start(1000, Qt::PreciseTimer, this);
}
};
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
Worker worker;
QThread workerThread;
worker.moveToThread(workerThread);
workerThread.start(QThread::HighPriority);
// Example of how to terminate the application after 10 seconds
// Requires Qt 5 and a C++11 compiler.
QTimer timer;
QObject::connect(&timer, &QTimer::timeout, [&](){
workerThread.quit();
workerThread.wait();
app.quit();
});
timer.setTimerType(Qt::VeryCoarseTimer);
timer.setSingleShot(true);
timer.start(10000);
return app.exec();
}
From the docs of QTimer class:
Accuracy and Timer Resolution
The accuracy of timers depends on the underlying operating system and
hardware. Most platforms support a resolution of 1 millisecond, though
the accuracy of the timer will not equal this resolution in many
real-world situations.
The accuracy also depends on the timer type. For Qt::PreciseTimer,
QTimer will try to keep the accurance at 1 millisecond. Precise timers
will also never time out earlier than expected.
For Qt::CoarseTimer and Qt::VeryCoarseTimer types, QTimer may wake up
earlier than expected, within the margins for those types: 5% of the
interval for Qt::CoarseTimer and 500 ms for Qt::VeryCoarseTimer.
All timer types may time out later than expected if the system is busy
or unable to provide the requested accuracy. In such a case of timeout
overrun, Qt will emit activated() only once, even if multiple timeouts
have expired, and then will resume the original interval.
Related
I have the following code:
mytimer.cpp
#include "mytimer.h"
#include <QtCore>
MyTimer::MyTimer()
{
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
timer->start(1000);
}
void MyTimer::mySlot()
{
qDebug()<<"timer executed";
}
and in the main.cpp
#include <QCoreApplication>
#include "mytimer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyTimer mtimer;
qDebug()<<"DONE";
return a.exec();
}
Now the output comes as:
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
I am really confused by this. How is that we are done with our main function and still the code for the SLOT mySlot() is getting executed?
What are the important aspects to this? that I need to understand?
Also what changes occurs when I modify mytimer.cpp MyTimer() to:
MyTimer::MyTimer()
{
timer = new QTimer(this);
QEventLoop eventloop;
connect(timer,SIGNAL(timeout()),this,SLOT(mySlot()));
connect(timer,SIGNAL(timeout()),&eventloop,SLOT(quit()));
timer->start(1000);
eventloop.exec();
}
There is one timer executed just before DONE is printed. To Be specific the output now becomes:
timer executed
DONE
timer executed
timer executed
...
...
...
...
infinite sequence
What caused that separate timer executed to appear above the DONE?
No - your main function is not done. It called a.exec() which will never return in your application.
a.exec() in turn processes a "message queue" which triggers all the timer events that call mySlot().
a.exec starts the event loop. It doesn't return a value until either QApplication::exit() or QApplication::quit() or all windows are closed.
What caused that separate timer executed to appear above the DONE?
The timer signals are always emitted from within the outermost event loop - because that's where the locus of control is (i.e. that's where the thread is running - it's inside Qt). Since you spun a local event loop (eventloop.exec();), that's where the timer invocation came from. As soon as that event loop was done and that exec() had returned, the MyTimer constructor had exited, DONE was printed out, and remaining timer invocations happen from the main event loop.
Generally speaking, code that nests event loops is broken, so if you ever find yourself with more than one exec() on the call stack, you're doing it wrong. There are a few notable exceptions: native dialogs on OS X require their own nested event loop due to OS X API deficiencies, and QDrag requires exec() also most likely due to platform deficiencies that require an exec() for portability, even if on some platforms it'd be unnecessary.
Disclaimer:I asked this question a few days ago on codereview,but got no answer.Here I change the question format from review request to a specific problems.
I am developing a video player with the following design:
The main thread - is GUI thread (Qt SDK).
Second thread - player thread which accepts commands from the GUI thread to play, forward, backward, stop etc. Now,this thread runs in a constant loop and and uses mutexes and wait conditions to live in sync with the main thread commands.
I have 2 problems with this code:
I don't feel my design is completely correct:I am using both mutex locks and atomic variables.I wonder if I can stay only with the atomics and use locks only for setting the wait conditions.
I am experiencing inconsistent bugs(probably due to the condition race when the play command tries to lock mutex which is already locked by the thread while the play loop is working) when I run "play" commands which activates a loop inside the thread loop. So I suppose it blocks the access to the shared variables to the main thread.
I have stripped off the code from unneeded stuff and it generally goes like this:
void PlayerThread::drawThread()//thread method passed into new boost::thread
{
//some init goes here....
while(true)
{
boost::unique_lock<boost::mutex> lock(m_mutex);
m_event.wait(lock); //wait for event
if(!m_threadRun){
break; //exit the tread
}
///if we are in playback mode,play in a loop till interrupted:
if(m_isPlayMode == true){
while(m_frameIndex < m_totalFrames && m_isPlayMode){
//play
m_frameIndex ++;
}
m_isPlayMode = false;
}else{//we are in a single frame play mode:
if(m_cleanMode){ ///just clear the screen with a color
//clear the screen from the last frame
//wait for the new movie to get loaded:
m_event.wait(lock);
//load new movie......
}else{ //render a single frame:
//play single frame....
}
}
}
}
Here are the member functions of the above class which send commands to the thread loop:
void PlayerThread::PlayForwardSlot(){
// boost::unique_lock<boost::mutex> lock(m_mutex);
if(m_cleanMode)return;
m_isPlayMode = false;
m_frameIndex++;
m_event.notify_one();
}
void PlayerThread::PlayBackwardSlot(){
// boost::unique_lock<boost::mutex> lock(m_mutex);
if(m_cleanMode)return;
m_isPlayMode = false;
m_frameIndex-- ;
if(m_frameIndex < 0){
m_frameIndex = 0;
}
m_event.notify_one();
}
void PlayerThread::PlaySlot(){
// boost::unique_lock<boost::mutex> lock(m_mutex);
if(m_cleanMode)return;
m_isPlayMode = true;
m_event.notify_one(); //tell thread to start playing.
}
All the flag members like m_cleanMode, m_isPlayMode and m_frameIndex are atomics:
std::atomic<int32_t> m_frameIndex;
std::atomic<bool> m_isPlayMode;
std::atomic<bool> m_cleanMode;
The questions summary::
Do I need mutex locks when using atomics?
Do I set waiting in the correct place inside the while loop of the
thread?
Any suggestion of a better design?
UPDATE:
Though I got an answer which seems to be in the right direction I don't really understand it.Especially the pseudo-code part which is talking about service.It is completely unclear to me how it would work.I would like to get a more elaborated answer.It is also strange that I received only one constructive answer to such a common problem.So I am resetting the bounty.
The biggest issue with your code is that you wait unconditionally. boost::condition::notify_one only wake up a thread which is waiting. Which means Forward Step\Backward Step then Play if fast enough will ignore the play command. I dont get clean mode, but you need at least
if(!m_isPlayMode)
{
m_event.wait(lock);
}
In your code stop and stepping to a frame are virtually the same thing .You may want to use a tristate PLAY,STEP, STOP to be able to use the recommended way of waiting on a condition variable
while(state == STOP)
{
m_event.wait(lock);
}
1. Do I need mutex locks when using atomics?
Technically yes. In this specific case I don't think so.
Current races conditions (I noticed) :
playing mode, playforward and playbackward will not result in the same m_frameIndex depending whether or not drawThread is within the while(m_frameIndex < m_totalFrames && m_isPlayMode) loop. Indeed m_frameIndexcould be incremented once or twice (playforward).
Entering the playing state in PlaySlot can be ignored if drawThread execute m_isPlayMode = false; before receiving the next event. Right now it is a non-issue because it will only happen if m_frameIndex < m_totalFrames is false. If PlaySlot was modifying m_frameIndex then you will have case of pushing play and nothing happen.
2. Do I set waiting in the correct place inside the while loop of the thread?
I would suggest to have only one wait in your code, for simplicity. And be explicit about the next thing to do using specific commands :
PLAY, STOP, LOADMOVIE, STEP
3. Any suggestion of a better design?
Use an explicit event queue. You can use one which is Qt-based (require Qthreads) or boost based. The one based on boost use a boost::asio::io_service and a boost::thread.
You start the event loop using :
boost::asio::io_service service;
//permanent work so io_service::exec doesnt terminate immediately.
boost::asio::io_service::work work(service);
boost::thread thread(boost::bind(&boost::asio::io_service::exec, boost::ref(service)));
Then you send your commands from the GUI using
MYSTATE state;
service.post(boost::bind(&MyObject::changeState,this, state));
Your play method should request another play given that the state hasn't changed, rather than looping. It allows a better user preemption.
Your step method should request a stop before displaying the frame.
Pseudocode:
play()
{
if(state != PLAYING)
return;
drawframe(index);
index++;
service.post(boost::bind(&MyObject::play, this));
}
stepforward()
{
stop();
index++;
drawframe(index);
}
stepbackward()
{
stop();
index--;
drawframe(index);
}
Edit:
There is only one player thread which is created once and execute only one event loop. Is is equivalent to QThread::start(). The thread will live as long as the loop doesnt return, which is going to be till the work object is destroyed OR when you explicitly stop the service. When you request to stop a service all posted tasks which are still pending are going to be executed first. You can interrupt the thread for fast exit if neccessary.
When there is a call for an action you post in the event loop ran by the player thread.
Note: You will probably need share pointers for the service and the thread. You will also need to put interrupt points in the play method in order to allow stopping the thread cleanly during playback. You don't need as much atomic as before. You don't need a condition variable anymore.
Any suggestion of a better design?
Yes! Since you are using Qt I would heavily suggest to use Qt's eventloop (apart from the UI stuff this is IMO one of the main selling points of that library) and asynchronous signal/slots to do the controlling instead of your homegrown synchronization, which - as you found out - is a very fragile undertaking.
The main change this will bring to your current design is that you will have to do your video logic as part of the Qt event-loop, or, easier, just do a QEventLoop::processEvents. For that you will need a QThread.
Then it's very straightforward: You create some class that inherits from QObject let's say PlayerController which should contain signals like play, pause, stop and a class Player which will have slots onPlay, onPause, onStop (or without the on, your preference). Then create a 'controller' object of the PlayerController class in the GUI thread and the Player object in the 'video' thread (or use QObject::moveToThread). This is important, as Qt has the notion of thread affinity to determine in which thread SLOTs are executed. No connect the objects by doing QObject::connect(controller, SIGNAL(play()), player, SLOT(onPlay())). Any call now to PlayerController:play on the 'controller' from the GUI thread will result in the onPlay method of the 'player' being executed in the video thread on the next event loop iteration. That's where you can then change your boolean status variables or do other kind of action without the need for explicit synchronization as your variables are only changes from the video thread now.
So something along those lines:
class PlayerController: public QObject {
Q_OBJECT
signals:
void play();
void pause();
void stop();
}
class Player: public QObject {
Q_OBJECT
public slots:
void play() { m_isPlayMode = true; }
void pause() { m_isPlayMode = false; }
void stop() { m_isStop = true; };
private:
bool m_isPlayMode;
bool m_isStop;
}
class VideoThread: public QThread {
public:
VideoThread (PlayerController* controller) {
m_controller = controller;
}
protected:
/* override the run method, normally not adviced but we want our special eventloop */
void run() {
QEventLoop loop;
Player* player = new Player;
QObject::connect(m_controller, SIGNAL(play()), player, SLOT(play()));
QObject::connect(m_controller, SIGNAL(pause()), player, SLOT(pause()));
QObject::connect(m_controller, SIGNAL(stop()), player, SLOT(stop()));
m_isStop = false;
m_isPlayMode = false;
while(!m_isStop) {
// DO video related stuff
loop.processEvents();
}
}
private:
PlayerController* m_controller;
}
// somewhere in main thread
PlayerController* controller = new PlayerController();
VideoThread* videoThread = new VideoThread(controller);
videoThread.start();
controller.play();
Any suggestion of a better design?
Instead of using separate thread, use QTimer and play on the main thread. No atomics or mutexes needed. I am not quite tracking with m_cleanMode, so I mostly took it out of the code. If you elaborate more on what it does, I cam add it to the code.
class Player
{
int32_t m_frameIndex;
bool m_cleanMode;
QTimer m_timer;
void init();
void drawFrame();
slots:
void play();
void pause();
void playForward();
void playBackward();
private slots:
void drawFrameAndAdvance();
}
void Player::init()
{
// some init goes here ...
m_timer.setInterval(333); // 30fps
connect(&m_timer, SIGNAL(timeout()), this, SLOT(drawFrameAndAdvance()));
}
void Player::drawFrame()
{
// play 1 frame
}
void Player::drawFrameAndAdvance()
{
if(m_frameIndex < m_totalFrames - 1) {
drawFrame();
m_frameIndex++;
}
else m_timer.stop();
}
void PlayerThread::playForward()
{
if(m_cleanMode) return;
m_timer.stop(); // stop playback
if(m_frameIndex < m_totalFrames - 1) {
m_frameIndex++;
drawFrame();
}
}
void PlayerThread::playBackward()
{
if(m_cleanMode)return;
m_timer.stop(); // stop playback
if(m_frameIndex > 0) {
m_frameIndex--;
drawFrame();
}
}
void PlayerThread::play()
{
if(m_cleanMode) return;
m_timer.start(); // start playback
}
void PlayerThread::pause()
{
if(m_cleanMode) return;
m_timer.stop(); // stop playback
}
I need a timeout function call. I work mainly with Qt (4.7.3, 4.8.5) and so i tried to find a solution with Qt. The two classes QFuture and QtConcurrent seems to do 99% of what i need but i can not find a possibility to timeout a function call.
My Problem:
I have my tester (gtest) and i test a function which can end in an infinity loop => so i want to test this to fix that problem[s] (this function is internal extrem complex :-( ). I want to add a timeout-time to break out if there is an infinity loop => so i can tell the tester that something is wrong (infinity loop) and i will terminate the thread.
I have search for something like that:
QtConcurrent::run(............,30000 /*30 seconds timeout)*/;
Does anybody know how i can do this?
(If it is possible with native C++, or boost, or ... you can also tell me your solution)
I was focusing on the QtConcurrent module, since you mentioned it in your question. But you can achieve your goal also with plain QThread:
// A Thread calling your test function
class MyThread : public QThread {
protected:
void run() { myFunction(); }
};
// calling the function
MyThread t;
t.start();
if ( t.wait(30000) ) {
// Finished
} else {
// Not finished
// ATTENTION: USE TERMINATE WITH CARE (see QThread documentation)!
t.terminate();
}
The call to terminate will forceably stop the thread and thus stop the execution of your function. Note however that the thread cannot cleanup, and any resources used by your function are not freed properly.
Old Answer:
You can do this with Qt, using a QFutureWatcher, a QTimer, and a helper QEventLoop . Setup your concurrent run, and watch the result with the watcher. Set the Timout with the timer, and wait until either is finished, in a Event loop.
// Setup eventloop, watcher and timer
QEventLoop loop;
QFutureWatcher watcher;
QObject::connect( &watcher, SIGNAL(finished()), &loop, SLOT(quit()));
QTimer::singleShot( 30000, &loop, SLOT(quit()) );
// Start function call
QFuture<T> future = QtConcurrent::run(...);
// Watch the call
watcher.setFuture( future );
// Wait until event loop finishes
loop.exec();
// Now either future has finished, or timeout was reached...
if ( future.isFinished() ) {
// Function completed!
} else {
future.cancel();
// Infinite loop...
}
The issue is that you cannot safely terminate a thread without thread's cooperation. The thread may be accessing some shared data structure, like the C-runtime heap, and if it is terminated forcefully then such data structures will remain in a mid-change state, essentially corrupted. Any future access to them from within the program will likely cause a crash or worse.
The case of an infinite loop is not by any means different from other bad scenarios. What if the function you launch crashes the program, how do you report it to the tester?
In your case you simply don't trust the code that you're executing. The solution is to launch it in a separate process, whose safe termination is guaranteed by the operating system. By isolating the tested code from the tester application you guarantee that you can detect all kind of problems, including timeouts or abnormal termination.
I think you need to find out why the infinite loop happens rather than trying to fix symptoms.
QtConcurrent::run() uses thread pool to run tasks. You can't safely terminate thread, so the only way to safely finish a task is to return from it.
If you still want timeouts, you can add something like this to your function with loop:
QTime t;
t.start();
// it's your loop
while( true ) {
if( t.elapsed() > 30*1000 ) {
return 1;
}
...
}
You can bind a QTimer signal to the slot:
auto process = QtConcurrent::run(...);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &process]() {
process.cancel();
});
timer->start(3000);
Edit: As the cancel() method won't work on the QtConcurrent::run function, the easiest thing would be to use some kind of isRunning flag:
bool isRunning = true;
void runnable() {
while (isRunning) {
...
}
}
auto process = QtConcurrent::run(runnable);
QTimer& timer = new QTimer();
connect(timer, &QTimer::timeout, [=, &isRunning]() {
isRunning = false;
});
timer->start(3000);
If possible, how do you mock the time for the purpose of triggering boost timers in a unit test?
For example, is it possible to achieve something like the following:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/)
{
std::cout << "Hello, world!\n";
}
int main()
{
boost::asio::io_service io; // Possibly another class needed here, or a way of setting the clock to be fake
boost::asio::deadline_timer t(io, boost::posix_time::hours(24));
t.async_wait(&print);
io.poll(); // Nothing should happen - no handlers ready
// PSEUDO-CODE below of what I'd like to happen, jump ahead 24 hours
io.set_time(io.get_time() + boost::posix_time::hours(24));
io.poll(); // The timer should go off
return 0;
}
Update Thank you to all the answers, they have provided excellent insight into the problem. I have provided my own answer (SSCCE), but couldn't have done that without the help provided.
The basic_deadline_timer template has a traits parameter which you can use to provide your own clock. The author of Boost Asio has a blog post showing how to do this. Here's an example from the post:
class offset_time_traits
: public asio::deadline_timer::traits_type
{
public:
static time_type now()
{
return add(asio::deadline_timer::traits_type::now(), offset_);
}
static void set_now(time_type t)
{
offset_ =
subtract(t, asio::deadline_timer::traits_type::now());
}
private:
static duration_type offset_;
};
typedef asio::basic_deadline_timer<
boost::posix_time::ptime, offset_time_traits> offset_timer;
Maybe you can use something like offset_timer throughout your application but only call set_now() when running your tests?
As far as I know, there is no way to emulate time change or to set the time with Boost. Before expanding upon a few techniques that can be used to approach this problem, there are a few points to consider:
Boost.Asio provides timers that use clocks, but does not provide clocks as they are outside of the scope of Boost.Asio. Thus, clock related features, such as setting or emulating, are not within Boost.Asio's capabilities.
Monotonic clocks may be used internally. Thus, a change in a clock (emulated or actual) may not produce the desired effect. For example, boost::asio::steady_timer will not be affected by changes to system time, and the reactor implementation using epoll can take up to 5 minutes before detecting changes to system time, as it is protected from changes to the system clock.
For Boost.Asio timers, changing the expiration time will implicitly cancel asynchronous wait operations per the WaitableTimerService and TimerService requirements. This cancellation causes outstanding asynchronous wait operations to complete as soon as possible, and cancelled operations will have an error code of boost::asio::error::operation_aborted.
Nevertheless, there are two overall techniques to approach this problem based on what is being tested:
Scaling time.
Wrapping types.
Scaling Time
Scaling time preserves the same overall relative flow between multiple timers. For example, a timer with a 1 second expiration should trigger before a timer with a 24 hour expiration. Minimum and maximum durations can also be used for additional control. Furthermore, scaling durations works for timers that are not affected by the system clock, as as the steady_timer.
Here is an example, where a scale of 1 hour = 1 second is applied. Thus, the 24 hour expiration will actual be a 24 second expiration.
Additionally,
namespace bpt = boost::posix_time;
const bpt::time_duration max_duration = bpt::seconds(24);
const boost::chrono::seconds max_sleep(max_duration.total_seconds());
bpt::time_duration scale_time(const bpt::time_duration& duration)
{
// Scale of 1 hour = 1 seconds.
bpt::time_duration value =
bpt::seconds(duration.total_seconds() * bpt::seconds(1).total_seconds() /
bpt::hours(1).total_seconds());
return value < max_duration ? value : max_duration;
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, scale_time(bpt::hours(24)));
t.async_wait(&print);
io.poll();
boost::this_thread::sleep_for(max_sleep);
io.poll();
}
Wrapping types
There are a few distinct locations where new types can be introduced to obtain some of the desired behavior.
Wrap the deadline_timer.
Create a custom WaitableTimerService.
Create a custom handler.
In all of these cases, it is important to account for the behavior that changing the expiration time will implicitly cancel the asynchronous wait operation.
Wrap the deadline_timer.
Wrapping the deadline_timer requires managing the user's handler internally. If the timer passes the user's handler to the service associated with the timer, then the user handler will be notified when the expiry time changes.
A custom timer could:
Store the WaitHandler provided to async_wait() internally (user_handler_).
When cancel() is invoked, an internal flag is set to indicate that cancellation has occurred (cancelled_).
Aggregate a timer. When an expiry time is set, an internal handler is passed to the aggregated timer's async_wait. Anytime the internal handler is called, it needs to handle the following four cases:
A normal timeout.
An explicit cancellation.
An implicit cancellation from expiry time being changed to a time is not in the future.
An implicit cancellation from expiry time being changed to a time that is in the future.
The internal handler code may look like the following:
void handle_async_wait(const boost::system::error_code& error)
{
// Handle normal and explicit cancellation.
if (error != boost::asio::error::operation_aborted || cancelled_)
{
user_handler_(error);
}
// Otherwise, if the new expiry time is not in the future, then invoke
// the user handler.
if (timer_.expires_from_now() <= boost::posix_time::seconds(0))
{
user_handler_(make_error_code(boost::system::errc::success));
}
// Otherwise, the new expiry time is in the future, so internally wait.
else
{
timer_.async_wait(boost::bind(&custom_timer::handle_async_wait, this,
boost::asio::placeholders::error));
}
}
While this is fairly easy to implement, it requires understanding the timer interface enough to mimic its pre/post-conditions, with the exception of the behavior for which you want to deviate. There may also be a risk factor in testing, as the behaviors need to be mimicked as close as possible. Additionally, this requires changing the type of timer for testing.
int main()
{
boost::asio::io_service io;
// Internal timer set to expire in 24 hours.
custom_timer t(io, boost::posix_time::hours(24));
// Store user handler into user_handler_.
t.async_wait(&print);
io.poll(); // Nothing should happen - no handlers ready
// Modify expiry time. The internal timer's handler will be ready to
// run with an error of operation_aborted.
t.expires_from_now(t.expires_from_now() - boost::posix_time::hours(24));
// The internal handler will be called, and handle the case where the
// expiry time changed to timeout. Thus, print will be called with
// success.
io.poll();
return 0;
}
Create a custom WaitableTimerService
Creating a custom WaitableTimerService is a little bit more complex. Although the documentation states the API, and the pre/post conditions, the implementation requires an understanding some of the internals, such as the io_service implementation and the scheduler interface, which is often a reactor. If the service passes the user's handler to the scheduler, then the user handler will be notified when the expiry time changes. Thus, similar to wrapping a timer, the user handler must be managed internally.
This has the same drawbacks as wrapping a timer: requires changing types and has inherit risk due to potential errors when trying to match the pre/post conditions.
For example:
deadline_timer timer;
is the equivalent of:
basic_deadline_timer<boost::posix_time::ptime> timer;
and would become:
basic_deadline_timer<boost::posix_time::ptime,
boost::asio::time_traits<boost::posix_time::ptime>,
CustomTimerService> timer;
Although this could be mitigated with a typedef:
typedef basic_deadline_timer<
boost::posix_time::ptime,
boost::asio::time_traits<boost::posix_time::ptime>,
CustomTimerService> customer_timer;
Create a custom handler.
A handler class could be used to wrap the actual handler, and provide the same approach as above with an extra degree of freedom. While this requires changing a type, and modifying what is provided to async_wait, it provides flexibility in that the custom handler's API has no pre-existing requirements. This reduced complexity provides a minimal risk solution.
int main()
{
boost::asio::io_service io;
// Internal timer set to expire in 24 hours.
deadline_timer t(io, boost::posix_time::hours(24));
// Create the handler.
expirable_handler handler(t, &print);
t.async_wait(&handler);
io.poll(); // Nothing should happen - no handlers ready
// Cause the handler to be ready to run.
// - Sets the timer's expiry time to negative infinity.
// - The internal handler will be ready to run with an error of
// operation_aborted.
handler.set_to_expire();
// The internal handler will be called, and handle the case where the
// expiry time changed to timeout. Thus, print will be called with
// success.
io.poll();
return 0;
}
All in all, testing asynchronous programs in a traditional manner can be very difficult. With proper encapsulation, it may even be nearly impossible to unit test without conditional builds. Sometimes it helps to shift perspectives and treat the entire asynchronous call chain as a single unit, with all external handlers being the API. If an asynchronous chain is too difficult to test, then I often find that the chain is too difficult to understand and/or maintain, and will mark it as a candidate for refactoring. Additionally, I often have to write helper types that allow my test harness to treat the asynchronous operations in a synchronous manner.
I dont' know about how to fake something like time passing, and I consider it to be overkill to provide your own time service. But here's a thought:
By initializing the timer with a hardcoded 24h, you used something that could be considered a magic constant (meaning: what you should not do). Instead, you could try this:
boost::asio::deadline_timer t(io, getDeadLineForX());
Now, if you stub out the getDeadLineForX function in your test suite, you can pass a sufficiently small deadline to test the timer, and you don't have to wait 24 hours for your test suite to complete.
A SSCCE, based on a link posted by #free_coffee:
#include <boost/asio.hpp>
#include <boost/optional.hpp>
class mock_time_traits
{
typedef boost::asio::deadline_timer::traits_type source_traits;
public:
typedef source_traits::time_type time_type;
typedef source_traits::duration_type duration_type;
// Note this implemenation requires set_now(...) to be called before now()
static time_type now() { return *now_; }
// After modifying the clock, we need to sleep the thread to give the io_service
// the opportunity to poll and notice the change in clock time
static void set_now(time_type t)
{
now_ = t;
boost::this_thread::sleep_for(boost::chrono::milliseconds(2));
}
static time_type add(time_type t, duration_type d) { return source_traits::add(t, d); }
static duration_type subtract(time_type t1, time_type t2) { return source_traits::subtract(t1, t2); }
static bool less_than(time_type t1, time_type t2) { return source_traits::less_than(t1, t2); }
// This function is called by asio to determine how often to check
// if the timer is ready to fire. By manipulating this function, we
// can make sure asio detects changes to now_ in a timely fashion.
static boost::posix_time::time_duration to_posix_duration(duration_type d)
{
return d < boost::posix_time::milliseconds(1) ? d : boost::posix_time::milliseconds(1);
}
private:
static boost::optional<time_type> now_;
};
boost::optional<mock_time_traits::time_type> mock_time_traits::now_;
typedef boost::asio::basic_deadline_timer<
boost::posix_time::ptime, mock_time_traits> mock_deadline_timer;
void handler(const boost::system::error_code &ec)
{
std::cout << "Handler!" << std::endl;
}
int main()
{
mock_time_traits::set_now(boost::posix_time::time_from_string("2013-01-20 1:44:01.000"));
boost::asio::io_service io_service;
mock_deadline_timer timer(io_service, boost::posix_time::seconds(5));
timer.async_wait(handler);
std::cout << "Poll 1" << std::endl;
io_service.poll();
mock_time_traits::set_now(mock_time_traits::now() + boost::posix_time::seconds(6));
std::cout << "Poll 2" << std::endl;
io_service.poll();
std::cout << "Poll 3" << std::endl;
io_service.poll();
return 0;
}
// Output
Poll 1
Poll 2
Handler!
Poll 3
Thankyou to #free_coffee for providing this link to a blog entry from the creator of boost asio. The above is slightly modified (and I believe slightly improved). By not using an offset on the system clock, you gain complete control over the timers: they will not fire until you explicitly set time forward past the timer.
The solution could be improved by making the this_thread::sleep part configurable. Note that the to_posix_duration hack described in [1] needs to use a smaller duration than the sleep.
To me this approach still seems a bit magic, since the time_traits are not well documented, and in particular the hack of to_posix_duration has a whiff of voodoo about it. I guess it just comes down to intimate knowledge of the deadline_timer implementation (which I don't have).
The problem I encountered is that I decided to implement QThreads the way they are supposed to, based on numerous articles:
https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
and issue at hand is that since the algorithm is run in separate QObject (wrapped in QThread). How can I call out something like Thread::Sleep or smth .. Any ideas?
A small description of the software.
Basically my application solves TSP (Traveling salesman problem). As the search goes along, it saves all the states in the history as frames ..(like visual frames). The search algorithms will be run on one thread.
Main thread is handling with the GUI.
Then there is the Mediaplayer like thread which tells Main thread what frame to display on screen. So where does the sleep come in ?
In gui there is a slider that user can use to fast forward or go in normal pace.. that slider tells via signal slot to Mediaplayer thread to go faster or slower.
What we've done is basically something like this: (written by memory, as I don't have our code checked out on this computer)
class Sleeper : public QThread {
public:
void sleep(int ms) { QThread::sleep(ms); }
};
void sleep(int ms);
// in a .cpp file:
static Sleeper slp;
void sleep(int ms) {
slp.sleep(ms);
}
The key is that the QThread::sleep function causes the calling thread to sleep, not the threaf represented by the QThread instance. So just create a wrapper which calls it via a custom QThread subclass.
Unfortunately, QThread is a mess. The documentation tells you to use it incorrectly. A few blog posts, as you've found, tell you a better way to do it, but then you can't call functions like sleep, which should never have been a protected thread member in the first place.
And best of all, even no matter which way you use QThread, it's designed to emulate what's probably the worst thread API ever conceived of, the Java one. Compared to something sane, like boost::thread, or even better, std::thread, it's bloated, overcomplicated and needlessly hard to use and requiring a staggering amount of boilerplate code.
This is really one of the places where the Qt team blew it. Big time.
The simple answer: you're not supposed to block in asynchronous, run-to-completion code -- every event handler and slot implementation in a QObject is supposed to do its job and return, as soon as possible. It's not supposed to do any sort of busy waiting or sleeping. For more ranting along this line, see Miro Samek's I hate RTOSes.
For a much better implementation that follows from the above, see this answer instead. Macro trickery that follows below is best left to the poor souls stuck with C.
I've attached an example of how to do it the right way at least from the point of view of what the code does. If you want a real implementation, look no farther than Boost's stackless coroutines.
The macro trickery is syntactic sugar - it makes the technique more palatable (Boost does it better than I do below). Whether you use macros or write out the methods explicitly, is up to you. The syntax is not what is claimed to be the "right way" of doing it. I'm not the only one to use such preprocessor trickery. Missing is support nested function calls, and multiple "threads" of run-to-completion execution within a QObject. The example shows code for only one "thread" and only one level of async function calls. Stackless Python takes this to the logical conclusion.
You'll see this pattern in all of your code if you write it in an asynchronous way. The SLEEP macro is syntax sugar to help make the code easier to follow. There's no truly clean way to write it without a hacky macro in C++ where the syntax wouldn't be overbearing. Even as of C++11, the language has no built-in support for yield. See Why wasn't yield added to C++0x?.
This is truly non-blocking code, you'll see that the periodic timer event fires while you're "asleep". Do note that this cooperative multitasking has a much lower overhead than thread/process switches done by the OS. There's a reason why 16 bit Windows application code was written this way: it performs quite well, even on meager hardware.
Note that this code does not need a QThread, and in fact doesn't use a QThread, although if you'd move the object to a high priority thread, the delays will have lower spread.
The Qt timer implementation is clever enough to decrease the timer tick period on Windows, if the period is "short". You can use the platform-specific code I show below, but it should be discouraged. On Qt 5, you'd simply start a Qt::PreciseTimer timer. Do note that on pre-Windows 8 systems you're trading off power consumption and a slightly higher kernel overhead for performance here. Windows 8, OS X (xnu) and modern Linux are tickless and don't suffer from such performance degradation.
I should acknowledge the clear preprocessor abuse direction from Creating C macro with ## and __LINE__ (token concatenation with positioning macro).
Similarly to the SLEEP() macro, you can also implement a GOTO() macro, to allow you having simple finite state machines that are written in an easier-to-follow blocking code style, yet are asynchronous behind the scenes. You can have ENTER() and LEAVE() macros to implement actions to be done on state entry and exit, etc, yet the code can look entirely like a straight-coded blocking-style function. I've found it quite productive, and easier to follow than code that lacks any syntactic sugarcoating. YMMV. In the end, you would have something that's on the way to UML statecharts, but with less overhead (both runtime and code-text-wise) than QStateMachine-based implementations.
Below is the output, the asterisks are periodic timer ticks.
doing something
*
*
*
*
*
*
*
*
*
*
slept, a=10
*
*
*
*
*
slept, a=20
*
*
slept, a=30
*
slept, a=40
#sleep.pro
QT += core
QT -= gui
TARGET = sleep
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
//main.cpp
#ifdef Q_WS_WIN
#include <windows.h>
#endif
#include <cstdio>
#include <QtCore/QTextStream>
#include <QtCore/QObject>
#include <QtCore/QBasicTimer>
#include <QtCore/QTimer>
#include <QtCore/QCoreApplication>
QTextStream out(stdout);
// this order is important
#define TOKENPASTE2(x,y) x ## y
#define TOKENPASTE(x,y) TOKENPASTE2(x,y)
#define SLEEP(ms) sleep(ms, &SLEEPCLASS::TOKENPASTE(fun, __LINE__)); } void TOKENPASTE(fun, __LINE__)() {
class Object : public QObject
{
Q_OBJECT
#define SLEEPCLASS Object // used by the SLEEP macro
public:
Object() {
QTimer::singleShot(0, this, SLOT(slot1()));
periodic.start(100);
connect(&periodic, SIGNAL(timeout()), SLOT(tick()));
}
protected slots:
void slot1() {
a = 10; // use member variables, not locals
out << "doing something" << endl;
sleep(1000, &Object::fun1);
}
void tick() {
out << "*" << endl;
}
protected:
void fun1() {
out << "slept, a=" << a << endl;
a = 20;
SLEEP(500);
out << "slept, a=" << a << endl;
a = 30;
SLEEP(250);
out << "slept, a=" << a << endl;
a = 40;
SLEEP(100);
out << "slept, a=" << a << endl;
qApp->exit();
}
private:
int a; // used in place of automatic variables
private:
void sleep(int ms, void (Object::*target)()) {
next = target;
timer.start(ms, this);
}
void timerEvent(QTimerEvent * ev)
{
if (ev->timerId() == timer.timerId()) {
timer.stop(); (this->*next)();
}
}
QTimer periodic;
QBasicTimer timer;
void (Object::* next)();
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Object o1;
#ifdef Q_WS_WIN
timeBeginPeriod(1); // timers will be accurate to 1ms
#endif
return a.exec();
}
#include "main.moc"
I agree with jalf. I have a thread that acts as a sort of DBUS daemon and needs to listen to messages forever. Two things to mention:
jalf has
void sleep(int ms) { QThread::sleep(ms); }
But this is NOT MILLISECONDS! QThread::sleep() takes seconds. Also, if one is to take this approach, he must also include the QThread lib anyway, so it might be easier to just make the call like this:
QThread::sleep(seconds);
directly in the code. That way there isn't an extra header file. I ran this and it also works as jalf explained. (putting the calling thread to sleep.)
For Qt 4.8.0 (the version I'm using), QThread::sleep, QThread::msleep and QThread::usleep have been made public so you can just call them directly. In earlier Qt versions, they were static protected.
e.g. QThread::sleep(5); // sleep for 5 seconds