1
0
Fork 0
mirror of https://gitlab.com/niansa/cosched.git synced 2025-03-06 20:53:26 +01:00

Simplified states and added suspension

This commit is contained in:
niansa/tuxifan 2023-05-04 11:04:02 +02:00
parent 31541ce918
commit eba003a721
2 changed files with 54 additions and 29 deletions

View file

@ -4,9 +4,7 @@
#include <vector>
#include <mutex>
#include <memory>
#include <limits>
#include <chrono>
#include <algorithm>
#include <async/result.hpp>
#include <async/recurring-event.hpp>
@ -25,8 +23,8 @@ enum {
enum class TaskState {
running,
sleeping,
starting,
stopping
terminating,
dead
};
@ -40,7 +38,8 @@ class Task {
std::string name;
Priority priority = PRIO_NORMAL;
TaskState state = TaskState::starting;
TaskState state = TaskState::running;
bool suspended = false;
public:
Task(Scheduler *scheduler, const std::string& name)
@ -70,6 +69,21 @@ public:
return *scheduler;
}
void terminate() {
if (state == TaskState::running) {
state = TaskState::terminating;
} else {
state = TaskState::dead;
}
}
void set_suspended(bool value = true) {
suspended = value;
}
bool is_suspended() const {
return suspended;
}
async::result<void> yield();
};
@ -111,12 +125,7 @@ class Scheduler {
std::mutex tasks_mutex;
std::vector<std::unique_ptr<Task>> tasks;
async::result<void> yield(Task *task);
void delete_task(Task *task) {
std::scoped_lock L(tasks_mutex);
tasks.erase(std::find_if(tasks.begin(), tasks.end(), [task] (const auto& o) {return o.get() == task;}));
}
void delete_task(Task *task);
Task *get_next_task();
@ -134,22 +143,10 @@ public:
return TaskPtr(tasks.emplace_back(std::make_unique<Task>(this, name)).get());
}
void run() {
while (!tasks.empty()) {
// Get next task
auto next_task = get_next_task();
// Resume task if any
if (next_task) next_task->resume.raise();
}
}
void run();
};
inline async::result<void> Task::yield() {
co_await scheduler->yield(this);
}
inline void TaskPtr::finalize() {
task->get_scheduler().delete_task(task);
}

View file

@ -1,12 +1,28 @@
#include "scheduler.hpp"
#include <limits>
#include <algorithm>
async::result<void> CoSched::Scheduler::yield(Task *task) {
task->state = TaskState::sleeping;
task->stopped_at = std::chrono::system_clock::now();
co_await task->resume.async_wait();
task->state = TaskState::running;
async::result<void> CoSched::Task::yield() {
if (state == TaskState::terminating) {
// If it was terminating, it can finally be declared dead now
state = TaskState::dead;
} else {
// It's just sleeping otherwise
state = TaskState::sleeping;
}
// Let's wait until we're back up!
stopped_at = std::chrono::system_clock::now();
co_await resume.async_wait();
state = TaskState::running;
}
void CoSched::Scheduler::delete_task(Task *task) {
std::scoped_lock L(tasks_mutex);
tasks.erase(std::find_if(tasks.begin(), tasks.end(), [task] (const auto& o) {return o.get() == task;}));
}
CoSched::Task *CoSched::Scheduler::get_next_task() {
@ -18,6 +34,8 @@ CoSched::Task *CoSched::Scheduler::get_next_task() {
for (auto& task : tasks) {
// Filter tasks that aren't sleeping
if (task->state != TaskState::sleeping) continue;
// Filter tasks that are suspended
if (task->suspended) continue;
// Update max priority
if (task->priority > max_prio) {
max_prio = task->priority;
@ -40,3 +58,13 @@ CoSched::Task *CoSched::Scheduler::get_next_task() {
// Return next task;
return next_task;
}
void CoSched::Scheduler::run() {
while (!tasks.empty()) {
// Get next task
auto next_task = get_next_task();
// Resume task if any
if (next_task) next_task->resume.raise();
}
}