2025-01-03 12:05:46 -05:00
|
|
|
#include "task_scheduler.h"
|
|
|
|
|
#include "core/plugin.h"
|
2025-05-19 20:19:38 +02:00
|
|
|
#include <chrono>
|
2025-01-03 12:05:46 -05:00
|
|
|
#include <limits>
|
2025-05-19 20:19:38 +02:00
|
|
|
#include <thread>
|
2025-01-03 12:05:46 -05:00
|
|
|
|
|
|
|
|
namespace satdump
|
|
|
|
|
{
|
|
|
|
|
void TaskScheduler::thread_func()
|
|
|
|
|
{
|
|
|
|
|
while (running)
|
|
|
|
|
{
|
2026-07-03 23:20:55 +02:00
|
|
|
std::shared_ptr<void> evt = nullptr;
|
|
|
|
|
std::string evt_name;
|
|
|
|
|
std::string task_to_run_name;
|
2025-01-03 12:05:46 -05:00
|
|
|
time_t sleep_for = std::numeric_limits<time_t>::max();
|
|
|
|
|
time_t wait_began = time(0);
|
|
|
|
|
|
2026-07-03 23:20:55 +02:00
|
|
|
// Lock the mutex and look for next task to run
|
2025-01-03 12:05:46 -05:00
|
|
|
{
|
2026-07-03 23:20:55 +02:00
|
|
|
std::unique_lock<std::mutex> lock(task_mtx);
|
|
|
|
|
|
|
|
|
|
for (auto &this_task : scheduled_tasks)
|
2025-01-03 12:05:46 -05:00
|
|
|
{
|
2026-07-03 23:20:55 +02:00
|
|
|
time_t next_run = this_task.second.last_run + this_task.second.run_interval;
|
|
|
|
|
if (next_run <= wait_began)
|
|
|
|
|
{
|
|
|
|
|
evt = this_task.second.evt;
|
|
|
|
|
evt_name = this_task.second.evt_name;
|
|
|
|
|
task_to_run_name = this_task.first;
|
|
|
|
|
sleep_for = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (sleep_for > next_run - wait_began)
|
|
|
|
|
{
|
|
|
|
|
sleep_for = next_run - wait_began;
|
|
|
|
|
evt = this_task.second.evt;
|
|
|
|
|
evt_name = this_task.second.evt_name;
|
|
|
|
|
task_to_run_name = this_task.first;
|
|
|
|
|
}
|
2025-01-03 12:05:46 -05:00
|
|
|
}
|
|
|
|
|
|
2026-07-03 23:20:55 +02:00
|
|
|
// Sleep until next task, or we are woken up
|
|
|
|
|
needs_update = false;
|
|
|
|
|
if (sleep_for > 0 && running && !needs_update)
|
2025-01-03 12:05:46 -05:00
|
|
|
{
|
2026-07-03 23:20:55 +02:00
|
|
|
cv.wait_for(lock, std::chrono::seconds(sleep_for), [this] { return !running || needs_update; });
|
2025-01-03 12:05:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-17 00:12:53 +02:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // TODOREWORK. Hogs CPU otherwise...
|
2025-01-03 12:05:46 -05:00
|
|
|
|
|
|
|
|
// Stop/Restart loop if needed
|
2026-07-03 23:20:55 +02:00
|
|
|
if (!running || needs_update || evt == nullptr || wait_began + sleep_for > time(NULL))
|
2025-01-03 12:05:46 -05:00
|
|
|
continue;
|
|
|
|
|
|
2026-07-03 23:20:55 +02:00
|
|
|
// Run the task that should be due now (without holding the lock!)
|
|
|
|
|
eventBus->fire_event(evt.get(), evt_name);
|
|
|
|
|
|
|
|
|
|
// Mark it for next run
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(task_mtx);
|
|
|
|
|
if (scheduled_tasks.count(task_to_run_name) > 0)
|
|
|
|
|
{
|
|
|
|
|
scheduled_tasks[task_to_run_name].last_run = time(NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-03 12:05:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-05 15:29:16 +02:00
|
|
|
TaskScheduler::TaskScheduler() {}
|
|
|
|
|
|
|
|
|
|
void TaskScheduler::start_thread() { task_thread = std::thread(&TaskScheduler::thread_func, this); }
|
2025-01-03 12:05:46 -05:00
|
|
|
|
|
|
|
|
TaskScheduler::~TaskScheduler()
|
|
|
|
|
{
|
|
|
|
|
running = false;
|
|
|
|
|
cv.notify_one();
|
|
|
|
|
if (task_thread.joinable())
|
|
|
|
|
task_thread.join();
|
|
|
|
|
}
|
2025-05-19 20:19:38 +02:00
|
|
|
} // namespace satdump
|