Allow Timer to be cancelled during callback execution

Useful for when e.g. a periodic timer needs to cancel itself
This commit is contained in:
JJL772
2024-06-10 15:30:29 -04:00
committed by mdavidsaver
parent 5552773e5e
commit bf36070860
2 changed files with 15 additions and 2 deletions

View File

@@ -60,6 +60,8 @@ private:
epicsTime timeToRun;
double period;
bool onList;
bool cancelled;
bool processing;
friend class Timer;
struct IncreasingTime;
};

View File

@@ -23,7 +23,9 @@ namespace epics { namespace pvData {
TimerCallback::TimerCallback()
: period(0.0),
onList(false)
onList(false),
cancelled(false),
processing(false)
{
}
@@ -50,6 +52,7 @@ void Timer::addElement(TimerCallbackPtr const & timerCallback)
temp.push_back(timerCallback);
timerCallback->onList = true;
timerCallback->cancelled = false;
// merge sorted lists.
// for us effectively insertion sort.
@@ -60,6 +63,11 @@ void Timer::addElement(TimerCallbackPtr const & timerCallback)
bool Timer::cancel(TimerCallbackPtr const &timerCallback)
{
Lock xx(mutex);
/* If we're processing, just set the cancel flag */
if (timerCallback->processing) {
timerCallback->cancelled = true;
return true;
}
if(!timerCallback->onList) return false;
if(!alive) {
timerCallback->onList = false;
@@ -107,6 +115,7 @@ void Timer::run()
TimerCallbackPtr work;
work.swap(queue.front());
work->onList = false;
work->processing = true;
queue.pop_front();
{
@@ -115,7 +124,9 @@ void Timer::run()
work->callback();
}
if(work->period > 0.0 && alive) {
work->processing = false;
if(work->period > 0.0 && alive && !work->cancelled) {
work->timeToRun += work->period;
addElement(work);
}