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:
parent
31541ce918
commit
eba003a721
2 changed files with 54 additions and 29 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue