1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#include "task_scheduler.h"
#include "core/plugin.h"
#include <limits>
namespace satdump
{
void TaskScheduler::thread_func()
{
while (running)
{
// Lock the mutex and set up
std::unique_lock<std::mutex> lock(task_mtx);
time_t sleep_for = std::numeric_limits<time_t>::max();
time_t wait_began = time(0);
ScheduledTask *task_to_run = nullptr;
// Look for next task to run
for (auto &this_task : scheduled_tasks)
{
// This task is already due! Run it
time_t next_run = this_task.second.last_run + this_task.second.run_interval;
if (next_run <= wait_began)
{
task_to_run = &this_task.second;
sleep_for = 0;
break;
}
// This task is the next one to run
else if (sleep_for > wait_began - next_run)
{
sleep_for = next_run - wait_began;
task_to_run = &this_task.second;
}
}
// Sleep until next task, or we are woken up
needs_update = false;
if (sleep_for > 0)
cv.wait_for(lock, std::chrono::seconds(sleep_for), [this] { return !running || needs_update; });
// Stop/Restart loop if needed
if (!running || needs_update || // We were woken up because of a change in the program
task_to_run == nullptr || // Spurious wake when no task scheduled
wait_began + sleep_for > time(NULL)) // Spurious wake
continue;
// Run the task that should be due now, and mark it for next run
eventBus->fire_event(task_to_run->evt.get(), task_to_run->evt_name);
task_to_run->last_run = time(NULL);
}
}
TaskScheduler::TaskScheduler()
{
task_thread = std::thread(&TaskScheduler::thread_func, this);
}
TaskScheduler::~TaskScheduler()
{
running = false;
cv.notify_one();
if (task_thread.joinable())
task_thread.join();
}
}
|