|
ControllableJob provides the following APIs to allow periodically running a background job:
/**
|
class ControllableJob {
|
public:
|
// Starts running the job.
|
virtual void start() = 0;
|
|
// Pauses the job temporarily so that it does not execute until unpaused.
|
virtual void pause() = 0;
|
|
// Resumes a paused job so that it continues executing each interval.
|
virtual void resume() = 0;
|
|
// Stops the job, this function blocks until the job is stopped.
|
virtual void stop() = 0;
|
};
|
This API could be extended to support waking background jobs:
class ControllableJob {
|
public:
|
...
|
/*
|
* Notifies the job to run so long as it's not paused or cancelled.
|
* The job should stop (or skip) waiting and run as soon as possible.
|
* Returns `false` if the job is already paused or cancelled, and `true` otherwise.
|
*/
|
virtual bool wakeUp() = 0;
|
...
|
};
|
A possible implementation for PeriodicJobImpl could be based on a bool member that records wakeUp attempts:
bool PeriodicRunnerImpl::PeriodicJobImpl::wakeUp() {
|
{
|
stdx::lock_guard lk(_mutex);
|
if (_execStatus != ExecutionStatus::RUNNING)
|
return false;
|
_notified = true;
|
}
|
_condvar.notify_one();
|
return true;
|
}
|
...
|
void PeriodicRunnerImpl::PeriodicJobImpl::_run() {
|
...
|
do {
|
auto deadline = getDeadlineFromInterval();
|
if (_clockSource->waitForConditionUntil(_condvar, lk, deadline, [&] {
|
return _notified || _execStatus == ExecutionStatus::CANCELED || getDeadlineFromInterval() != deadline;
|
})) {
|
if (_execStatus == ExecutionStatus::CANCELED) {
|
return;
|
}
|
if (std::exchange(_notified, false)) {
|
break;
|
}
|
}
|
} while (_clockSource->now() < getDeadlineFromInterval());
|
...
|
}
|
|