General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

97 regels
2.2 KiB

#pragma once
#include "gp/system/system.hpp"
namespace gp{
class simple_scheduling : public gp::scheduling_scheme {
struct locked_circular_buffer {
std::atomic_bool lock;
gp::array<gp::topic_list::node_ptr, gp_config::limits::max_processes> processes;
size_t read_idx = 0;
size_t write_idx = 0;
void push(gp::topic_list::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::topic_list::node_ptr pop() {
bool t = true;
bool f = false;
gp::topic_list::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::topic_list::node_ptr one(size_t) {
auto v = running.pop();
do{
if(v) return v;
v = running.pop();
}while(true);
}
virtual void push(gp::topic_list::node_ptr node) {
running.push(node);
}
virtual gp::topic_list::node_ptr next(size_t, gp::topic_list::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::scheduler& current_scheduler() {
return sys->process_managers[0];
}
};
}