#pragma once
|
|
#include "gp/system/system.hpp"
|
|
|
|
// TODO: implement unsafe_bottleneck to use in the locked list
|
|
|
|
namespace gp{
|
|
namespace system {
|
|
class simple_scheduling : public gp::system::scheduling_scheme {
|
|
struct locked_circular_buffer {
|
|
std::atomic_bool lock;
|
|
gp::array<gp::system::task_queue::node_ptr, gp_config::limits::max_processes> processes;
|
|
size_t read_idx = 0;
|
|
size_t write_idx = 0;
|
|
|
|
void push(gp::system::task_queue::node_ptr node) {
|
|
bool t = true;
|
|
bool f = false;
|
|
while(not lock.compare_exchange_strong(f,t)){}
|
|
{
|
|
gp_config::assertion((write_idx + 1)%processes.size() != read_idx, "bad push to circular buffer");
|
|
processes[write_idx] = node;
|
|
write_idx=(write_idx+1)%processes.size();
|
|
}
|
|
while(not lock.compare_exchange_strong(t,f)){}
|
|
}
|
|
|
|
gp::system::task_queue::node_ptr pop() {
|
|
bool t = true;
|
|
bool f = false;
|
|
gp::system::task_queue::node_ptr ret;
|
|
while(not lock.compare_exchange_strong(f,t)){}
|
|
{
|
|
if(read_idx == write_idx) {
|
|
ret = nullptr;
|
|
} else {
|
|
ret = processes[read_idx];
|
|
read_idx=(read_idx+1)%processes.size();
|
|
}
|
|
}
|
|
while(not lock.compare_exchange_strong(t,f)){}
|
|
return ret;
|
|
}
|
|
|
|
};
|
|
|
|
|
|
locked_circular_buffer running;
|
|
locked_circular_buffer waiting;
|
|
locked_circular_buffer to_clean;
|
|
locked_circular_buffer naughty;
|
|
system* sys = nullptr;
|
|
|
|
public:
|
|
simple_scheduling()
|
|
{}
|
|
|
|
virtual void link(system& value) {
|
|
gp_config::assertion(!(sys), "Double linkage detected");
|
|
sys = &value;
|
|
|
|
sys->process_managers.emplace_back(*sys,0);
|
|
}
|
|
|
|
virtual gp::system::task_queue::node_ptr one(size_t) {
|
|
auto v = running.pop();
|
|
do{
|
|
if(v) return v;
|
|
v = running.pop();
|
|
}while(true);
|
|
}
|
|
|
|
virtual void push(gp::system::task_queue::node_ptr node) {
|
|
running.push(node);
|
|
}
|
|
|
|
virtual gp::system::task_queue::node_ptr next(size_t, gp::system::task_queue::node_ptr current) {
|
|
switch(current->value->state) {
|
|
case process_status::inactive:
|
|
case process_status::running:
|
|
running.push(current);
|
|
break;
|
|
case process_status::finished:
|
|
to_clean.push(current);
|
|
break;
|
|
case process_status::zombie:
|
|
naughty.push(current);
|
|
break;
|
|
case process_status::waiting:
|
|
waiting.push(current);
|
|
break;
|
|
}
|
|
return one(0);
|
|
}
|
|
|
|
virtual gp::system::scheduler& current_scheduler() {
|
|
return sys->process_managers[0];
|
|
}
|
|
};
|
|
}
|
|
}
|