MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/systemic/ValueManager.hpp

257 lines
7.4 KiB
C++
Raw Permalink Blame History

/*
* ValueManager.hpp
*
* Created on: 24 <20><><EFBFBD><EFBFBD>. 2018 <20>.
* Author: titov
*/
#ifndef SOURCE_SYSTEMIC_VALUEMANAGER_HPP_
#define SOURCE_SYSTEMIC_VALUEMANAGER_HPP_
#include "IValue.hpp"
#include "IValueOverride.hpp"
#include "ValueImplementation.hpp"
#include "../memories/memories.hh"
namespace systemic {
template< typename BaseType,
class Interface = IValue<BaseType>,
class InterfaceOverride = IValueOverride<BaseType> >
class ValueManager {
public:
typedef unsigned short Id;
typedef BaseType Type;
typedef Interface InterfaceType;
typedef InterfaceOverride InterfaceOverrideType;
class Record {
friend class ValueManager;
Interface * obj;
InterfaceOverride * override;
volatile const BaseType * value;
Id id;
Record( Id id, Interface * obj, InterfaceOverride * override, volatile const BaseType * value ) :
obj(obj), override(override), id(id), value(value) {}
public:
Record() :
obj(nullptr), override(nullptr), value(nullptr), id(0) {}
bool exist() const {
return id;
}
};
struct NotificationInterface {
virtual void notify( Id id, Interface * interface, InterfaceOverride * override, volatile const BaseType * value ) = 0;
virtual ~NotificationInterface() = default;
};
static NotificationInterface & getDefault() {
struct DefaultHerald : public NotificationInterface {
void notify( Id id, Interface * interface, InterfaceOverride * override, volatile const BaseType * value ) {}
};
static DefaultHerald herald;
return herald;
}
private:
const std::size_t size;
Record * const records;
std::pmr::memory_resource* allocator;
NotificationInterface & herald;
bool place_in_parnas( Id id, const volatile BaseType * value,
Interface * interface, InterfaceOverride * override );
protected:
virtual Record & search( Id id ) const;
public:
ValueManager( Record * recods, std::size_t size, std::pmr::memory_resource* allocator, NotificationInterface & herald = getDefault() );
template< class Implemetation = ValueImplementation<BaseType> >
Interface * create( Id id, const volatile BaseType & value, std::pmr::memory_resource* = nullptr );
Interface * get( Id id ) const;
virtual bool add( Id id, Interface * interface, InterfaceOverride * override = nullptr, volatile const BaseType * value = nullptr );
InterfaceOverride * getOverride( Id id );
volatile const BaseType * getValue( Id id ) const;
//todo: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
bool insert( Id id, Interface * interface, InterfaceOverride * override, volatile const BaseType * value );
};
template<std::size_t num, typename BaseType, class Interface = IValue<BaseType>,
class InterfaceOverride = IValueOverride<BaseType> >
struct ValueManagerBox {
typename ValueManager<BaseType, Interface, InterfaceOverride>::Record records[num];
ValueManager<BaseType, Interface, InterfaceOverride> manager;
ValueManagerBox( void * (*allocator)( std::size_t size, std::size_t aligment ) ) :
records(), manager( records, num, allocator ) {}
};
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline systemic::ValueManager<BaseType, Interface, InterfaceOverride>::ValueManager(
Record * records, std::size_t size,
std::pmr::memory_resource* allocator, NotificationInterface & herald ) :
records(records), size(size), allocator(allocator),
herald(herald) {}
template<typename BaseType, class Interface, class InterfaceOverride>
template<class Implemetation>
inline Interface * systemic::ValueManager<BaseType, Interface, InterfaceOverride>::create(
Id id, const volatile BaseType & value,
std::pmr::memory_resource* allocator_local ) {
typedef Implemetation Imp;
Interface * interface( nullptr );
if( not get( id ) ) {
Imp * impl = memories::instance_object<Imp>( *(allocator_local ? allocator_local : allocator), value );
interface = impl->getValue();
if( not add( id, interface, impl->getValueOverride(), impl->getBase() ) ) {
interface = nullptr;
}
}
return interface;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline Interface * systemic::ValueManager<BaseType, Interface, InterfaceOverride>::get(
Id id ) const {
return search(id).obj;
}
template<typename BaseType, class Interface, class InterfaceOverride>
bool systemic::ValueManager<BaseType, Interface, InterfaceOverride>::place_in_parnas(
Id id, const volatile BaseType * value,
Interface * interface, InterfaceOverride * override) {
bool result = false;
for( int i = 0; i < size && !result; i++ )
if( !records[i].obj or records[i].id == id ) {
records[i] = Record(id, interface, override, value);
result = true;
}
return result;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline bool systemic::ValueManager<BaseType, Interface, InterfaceOverride>::add(
Id id, Interface * interface, InterfaceOverride * override,
const volatile BaseType * value ) {
bool result = false;
if( id < size ) {
Record old = records[id];
records[id] = Record( id, interface, override, value );
if( old.obj )
result = place_in_parnas(old.id, old.value, old.obj, old.override);
else
result = true;
} else
result = place_in_parnas(id, value, interface, override);
if( result )
herald.notify(id, interface, override, value);
return result;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline InterfaceOverride * systemic::ValueManager<BaseType, Interface, InterfaceOverride>::getOverride( Id id ) {
return search(id).override;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline typename systemic::ValueManager<BaseType, Interface, InterfaceOverride>::Record & systemic::ValueManager<BaseType, Interface, InterfaceOverride>::search(
Id id ) const {
static systemic::ValueManager<BaseType, Interface, InterfaceOverride>::Record null_object;
if( id < size )
return records[id].id == id ? records[id] : null_object;
else
for( int i = 0; i < size; i++ )
if( records[i].id == id )
return records[i];
return null_object;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline volatile const BaseType * systemic::ValueManager<BaseType, Interface, InterfaceOverride>::getValue( Id id ) const {
return search(id).value;
}
template<typename BaseType, class Interface, class InterfaceOverride>
inline bool systemic::ValueManager<BaseType, Interface, InterfaceOverride>::insert(
Id id, Interface * interface, InterfaceOverride * override,
const volatile BaseType * value) {
bool result = false;
if( id < size ) {
Record old = records[id];
records[id] = Record( id, interface, override, value );
if( old.obj )
result = place_in_parnas(old.id, old.value, old.obj, old.override);
else
result = true;
} else
result = place_in_parnas(id, value, interface, override);
return result;
}
#endif /* SOURCE_SYSTEMIC_VALUEMANAGER_HPP_ */