257 lines
7.4 KiB
C++
257 lines
7.4 KiB
C++
/*
|
|
* ValueManager.hpp
|
|
*
|
|
* Created on: 24 пїЅпїЅпїЅпїЅ. 2018 пїЅ.
|
|
* 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: Спрятать.
|
|
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_ */
|