76 lines
1.6 KiB
C++
76 lines
1.6 KiB
C++
|
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||
|
//SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
|
||
|
#include "scheduler.h"
|
||
|
|
||
|
TM::Scheduler::Scheduler (std::weak_ptr<Manager> manager):
|
||
|
manager(manager),
|
||
|
queue(),
|
||
|
mutex(),
|
||
|
cond(),
|
||
|
thread(nullptr),
|
||
|
running(false)
|
||
|
{}
|
||
|
|
||
|
TM::Scheduler::~Scheduler () {
|
||
|
stop();
|
||
|
}
|
||
|
|
||
|
void TM::Scheduler::start () {
|
||
|
std::unique_lock lock(mutex);
|
||
|
if (running)
|
||
|
return;
|
||
|
|
||
|
running = true;
|
||
|
thread = std::make_unique<std::thread>(&Scheduler::loop, this);
|
||
|
}
|
||
|
|
||
|
void TM::Scheduler::stop () {
|
||
|
std::unique_lock lock(mutex);
|
||
|
if (!running)
|
||
|
return;
|
||
|
|
||
|
running = false;
|
||
|
|
||
|
lock.unlock();
|
||
|
cond.notify_all();
|
||
|
thread->join();
|
||
|
|
||
|
lock.lock();
|
||
|
thread.reset();
|
||
|
}
|
||
|
|
||
|
void TM::Scheduler::loop () {
|
||
|
while (running) {
|
||
|
std::unique_lock<std::mutex> lock(mutex);
|
||
|
if (queue.empty()) {
|
||
|
cond.wait(lock);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
Time currentTime = std::chrono::steady_clock::now();
|
||
|
while (!queue.empty()) {
|
||
|
Time nextScheduledTime = queue.top().first;
|
||
|
if (nextScheduledTime > currentTime) {
|
||
|
cond.wait_until(lock, nextScheduledTime);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Task task = queue.top().second;
|
||
|
queue.pop();
|
||
|
lock.unlock();
|
||
|
task();
|
||
|
lock.lock();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void TM::Scheduler::schedule (Task task, Delay delay) {
|
||
|
std::unique_lock lock(mutex);
|
||
|
Time time = std::chrono::steady_clock::now() + delay;
|
||
|
queue.emplace(time, task);
|
||
|
|
||
|
lock.unlock();
|
||
|
cond.notify_one();
|
||
|
}
|