257 lines
7.4 KiB
C++
257 lines
7.4 KiB
C++
/*
|
||
* 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_ */
|