1
\$\begingroup\$

I have a Visual Studio 2008 C++03 project where I need a timer. I have an implementation that works well, but I'd like any general suggestions from the community on how to improve it. (More generic, lower cost of creating timers, etc...)

class Timer
{
public:
 typedef boost::function< void( ) > OnTimer;
 Timer( const OnTimer& f, DWORD timeout )
 : cancel_event_( ::CreateEvent( NULL, FALSE, FALSE, NULL ), ::CloseHandle ),
 timer_thread_( boost::bind( &Timer::TimerThread, cancel_event_.get(), f, timeout ) ),
 timeout_( timeout )
 {
 };
 ~Timer() { ::SetEvent( cancel_event_.get() ); };
 DWORD Timeout() const { return timeout_; };
private:
 static void TimerThread( HANDLE cancel_event, const OnTimer& f, DWORD timeout )
 {
 if( WAIT_OBJECT_0 != ::WaitForSingleObject( cancel_event, timeout ) )
 f();
 };
 /// time to wait for the timer to fire
 UINT timeout_;
 /// event signaled when the timer should be canceled
 boost::shared_ptr< void > cancel_event_;
 /// thread that runs the timer (similar to boost::thread, but doesn't require `localtime`, `gmtime`, or `abort`)
 util::CThread timer_thread_;
}; // class Timer

Preemptive:

  • My project does not have a window message pump so SetTimer is unsuitable.
  • I do not want to incur the cost of importing the mmtimer library.
  • I can only use boost header libraries, therefore boost::timer is unsuitable.
  • I would prefer to keep the discussion limited to this block of code.
palacsint
30.4k9 gold badges82 silver badges157 bronze badges
asked May 15, 2012 at 20:42
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I think that you can create one thread to handle all timers. When a new timer is created, you should add it in a (synchronized) queue of "timers to trigger". The background thread must wait for the closest timer to be triggered. Also you should wake it up each time you modify the queue of timers and recalculate "which is the closest timer now?".

When the queue is empty, the background thread can be destroyed (joined) or you can wait an "exit" event (or the creation of another timer). Those are just details. The background thread can be created by the first timer and joined when the last timer is destroyed, or it can just live in the whole program execution.

Another thing, to improve portability you could use boost::thread library and boost's condition variables instead of raw Windows events.

answered May 15, 2012 at 23:42
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.