#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 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]; } }; }