The constructor for the timer class has a ‘one_shot’ parameter allowing you to specify whether you want your Timer to fire once, or repeatedly until stop() is called.
In the following code I’m attempting to create an NTimesTimer, such that it will fire n-times and then stop/dispose itself:
class NTimesTimer {
public:
NTimesTimer(int n, int delay, void (*callback)(void), void (*onComplete)(void));
void start();
private:
int _n;
void (*_callback)(void);
void (*_onComplete)(void);
void _countdown();
Timer _timer;
};
NTimesTimer::NTimesTimer(int n, int delay, void (*callback)(void), void (*onComplete)(void))
: _timer(delay, &NTimesTimer::_countdown, *this) {
_n = n;
_callback = callback;
_onComplete = onComplete;
}
void NTimesTimer::start() {
_timer.start();
}
void NTimesTimer::_countdown() {
if ( _n > 0 ) {
_n = _n - 1;
if ( _callback ) {
_callback();
}
} else if ( _onComplete ) {
_onComplete();
_timer.dispose();
}
}
It mostly works except that I am not able to use it more than once. For example, this works:
After you called _timer.dispose() your local Timer will be non-existent for any further use.
Either you don’t dispose the timer or you have to instantiate a Timer in start() each time anew.
If you go for the former, I’d suggest to also provide a destructor that does the disposing once your object dies.
Yes, of course, I missed that I just read that bit: “It mostly works except that I am not able to use it more than once.” , and the class implementation.
What puzzles me is the constructor definition. It looks like it calls _timer constructor as its base class. My C++ knowledge is bit rusty, so please correct me if I am wrong.
This is the suspicious part:
NTimesTimer::NTimesTimer(int n, int delay, void (*callback)(void), void (*onComplete)(void)) *: _timer(delay, &NTimesTimer::_countdown, this) {
That part of the timer declaration is most likely correct. I tested it when I posted this:
The part after the colon on a C++ constructor implementation can initialize the base class as well as any class member variables. And if the member variable is a class, and it has a constructor that takes parameters, you can set the constructor parameters there.
Ok, so the issue I’m currently encountering is that I don’t think it is possible to call timer.dispose() from within a timer callback. It’s possible this is the source of my difficulties above.
Edit: Yup that was it. Once I moved the call to ->dispose() outside of the timer callback, it started working. Not ideal, but workable.
OK, I think I found a way to go.
First, as suggested earlier I added a destructor which does the disposing, and only stop the timer when finished.
Additionally I think there is sligtly flaw in the logic here
void NTimesTimer::_countdown() {
if ( _n > 0 ) {
_n = _n - 1;
if ( _callback ) {
_callback();
}
} else if ( _onComplete ) {
_onComplete();
_timer.dispose(); // <-- this should happen, even if `onComplete == NULL
}
}
In my current use case for the above class, I’ll only ever have one of them running at a single time. So I ended up reusing the same timer, and eliminating the need to dispose, etc.