199 lines
5.0 KiB
C++
199 lines
5.0 KiB
C++
/*
|
||
* Scheduler.hpp
|
||
*
|
||
* Created on: 13 июл. 2019 г.
|
||
* Author: titov
|
||
*/
|
||
|
||
#ifndef SOURCE_SYSTEMIC_SCHEDULER_HPP_
|
||
#define SOURCE_SYSTEMIC_SCHEDULER_HPP_
|
||
|
||
#include <utility>
|
||
#include <cstddef>
|
||
#include <stdexcept>
|
||
#include <memory_resource>
|
||
|
||
#include "IProcessor.hh"
|
||
|
||
#include "../common/Result.hh"
|
||
#include "../memories/allocator.hh"
|
||
#include "../memories/instance_object.hpp"
|
||
|
||
namespace systemic {
|
||
|
||
typedef typename std::pair<systemic::IProcess *, systemic::IProcessor::Priority> ProcessInfo;
|
||
|
||
template<unsigned tag_id>
|
||
struct Scheduler {
|
||
|
||
static const unsigned tag = tag_id;
|
||
|
||
typedef IProcessor::Priority Priority;
|
||
typedef IProcessor::Period Period;
|
||
typedef IProcessor::Phase Phase;
|
||
typedef IProcessor::Controlled Controlled;
|
||
|
||
// static Result< void, Error > runOnce();
|
||
static void runOnce();
|
||
static void setSampleTime( float ts_in_second );
|
||
|
||
protected:
|
||
static ProcessInfo * table;
|
||
static std::size_t size;
|
||
static std::pmr::memory_resource * allocator;
|
||
|
||
static void reqisterProcess( Priority priority, Period period, Phase phase, Controlled controlled, IProcess & proc );
|
||
|
||
static float ts_in_second;
|
||
static std::size_t proc_count;
|
||
};
|
||
|
||
template<typename Scheduler>
|
||
struct SchedulerInterface : public IProcessor, public Scheduler {
|
||
|
||
typedef unsigned Tag;
|
||
static const Tag tag = Scheduler::tag;
|
||
|
||
std::size_t count_proc = 0;
|
||
|
||
SchedulerInterface( ProcessInfo * table,
|
||
std::size_t size,
|
||
std::pmr::memory_resource * allocator = std::pmr::get_default_resource() );
|
||
|
||
void reqisterProcess( Priority priority, Period period, Phase phase, Controlled controlled, IProcess & proc );
|
||
|
||
};
|
||
|
||
struct SparseProcess : public IProcess {
|
||
|
||
const IProcessor::Period period;
|
||
IProcessor::Period counter;
|
||
IProcess & proc;
|
||
|
||
SparseProcess( IProcessor::Period period, IProcess & proc );
|
||
|
||
void process();
|
||
|
||
};
|
||
|
||
}
|
||
|
||
template<unsigned tag_id>
|
||
std::size_t systemic::Scheduler<tag_id>::proc_count = 0;
|
||
|
||
template<unsigned tag_id>
|
||
systemic::ProcessInfo * systemic::Scheduler<tag_id>::table = 0;
|
||
|
||
template<unsigned tag_id>
|
||
std::pmr::memory_resource * systemic::Scheduler<tag_id>::allocator = nullptr;
|
||
|
||
template<unsigned tag_id>
|
||
std::size_t systemic::Scheduler<tag_id>::size = 0;
|
||
|
||
template<unsigned tag_id>
|
||
float systemic::Scheduler<tag_id>::ts_in_second = 0.0f;
|
||
|
||
template<unsigned tag_id>
|
||
inline void systemic::Scheduler<tag_id>::reqisterProcess(
|
||
Priority priority, Period period, Phase phase, Controlled controlled,
|
||
IProcess & proc ) {
|
||
|
||
if( proc_count < size ) {
|
||
|
||
IProcess * proc_interface = &proc;
|
||
|
||
if( allocator and period )
|
||
proc_interface = ::memories::instance_object<SparseProcess>(*allocator, period, proc);
|
||
|
||
table[proc_count] = std::make_pair( proc_interface, priority );
|
||
|
||
for( std::size_t i = proc_count; i > 0; i-- )
|
||
if( table[i-1].second > priority )
|
||
std::swap(table[i], table[i-1]);
|
||
|
||
|
||
proc_count++;
|
||
proc.setSampleTime( period ? period * ts_in_second : ts_in_second );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<unsigned tag_id>
|
||
//inline Result< void, Error > systemic::Scheduler<tag_id>::runOnce() {
|
||
inline void systemic::Scheduler<tag_id>::runOnce() {
|
||
// FIXME Реализовать возвраты
|
||
// typedef Result< void, Error > Result;
|
||
|
||
for( std::size_t j = 0; j < proc_count; ++j ) {
|
||
|
||
systemic::IProcess * proc = table[j].first;
|
||
|
||
if ( proc == nullptr ) continue;
|
||
|
||
proc->process();
|
||
|
||
//#if __cplusplus >= 201103L
|
||
// if ( status.isErr() ) {
|
||
// table[j].first = nullptr;
|
||
// return Result(std::move(status));
|
||
// }
|
||
//#else
|
||
// if ( status.isErr() ) {
|
||
// table[j].first = nullptr;
|
||
// return Result(status);
|
||
// }
|
||
//#endif
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<unsigned tag_id>
|
||
inline void systemic::Scheduler<tag_id>::setSampleTime( float sample_time ) {
|
||
|
||
if( ts_in_second != sample_time ) {
|
||
|
||
ts_in_second = sample_time;
|
||
for( std::size_t j = 0; j < proc_count; ++j )
|
||
table[j].first->setSampleTime( ts_in_second );
|
||
|
||
}
|
||
|
||
}
|
||
|
||
template<typename Scheduler>
|
||
inline systemic::SchedulerInterface<Scheduler>::SchedulerInterface(
|
||
ProcessInfo * table, std::size_t size, std::pmr::memory_resource * allocator ) {
|
||
|
||
Scheduler::table = table;
|
||
Scheduler::size = size;
|
||
Scheduler::allocator = allocator;
|
||
|
||
}
|
||
|
||
template<typename Scheduler>
|
||
inline void systemic::SchedulerInterface<Scheduler>::reqisterProcess(
|
||
Priority priority, Period period, Phase phase, Controlled controlled,
|
||
IProcess & proc ) {
|
||
|
||
count_proc++;
|
||
|
||
Scheduler::reqisterProcess(priority, period, phase, controlled, proc);
|
||
|
||
}
|
||
|
||
inline systemic::SparseProcess::SparseProcess(IProcessor::Period period,
|
||
IProcess & proc ) : proc(proc), period(period), counter(0) {}
|
||
|
||
inline void systemic::SparseProcess::process() {
|
||
|
||
if( ++counter == period ) {
|
||
counter = 0;
|
||
proc.process();
|
||
}
|
||
|
||
}
|
||
|
||
#endif /* SOURCE_SYSTEMIC_SCHEDULER_HPP_ */
|