/* * SettingValue.h * * Created on: 15 июн. 2020 г. * Author: user */ #ifndef UMLIBRARY_SYSTEMIC_SETTINGVALUE_HH_ #define UMLIBRARY_SYSTEMIC_SETTINGVALUE_H_ #include "IValueAsync.hpp" #include "SharedData.hh" #include #include #include #include "SystemException.hh" namespace systemic { //! Класс реализует интерфейс доступа к полю настройки. template class SettingValue : public IValueType { private: mutable systemic::SharedData data; const std::size_t offset; const ValueType min; const ValueType max; public: struct Constraints { ValueType min; ValueType max; }; void set( ValueType value ); ValueType get() const; SettingValue( systemic::SharedData data, const Constraints & constraints, size_t offset ); }; //! Класс реализует интерфейс кешируемого доступа к полю настройки. template class SettingCachedValue : public SettingValue { ValueType cached; public: void set( ValueType value ); ValueType get() const; void update(); SettingCachedValue( systemic::SharedData data, const typename SettingValue::Constraints & constraints, size_t offset ); }; //! Шаблонная версия класса для доступа к полю настройки. template struct ConcreteSettingValue : public IValueType { private: mutable systemic::SharedData data; char * const base_pointer; ValueType & getValue() { return ( reinterpret_cast(base_pointer) )->*member_p; } ValueType & getValue() const { return ( reinterpret_cast(base_pointer) )->*member_p; } const ValueType min; const ValueType max; public: struct Constraints { ValueType min; ValueType max; }; void set( ValueType value ); ValueType get() const; ConcreteSettingValue( systemic::SharedData data, const Constraints & constraints ); }; struct SetValueError : public SystemException { SetValueError( float mx, float mn, float value ) : mx(mx), mn(mn), value(value) {} std::size_t id() const noexcept { return 54; } std::pair binary() const noexcept { return {reinterpret_cast( this ), sizeof(*this)}; } const char * what() const noexcept { return "Set Value Error"; } float mx; float mn; float value; }; struct IncorrectData : public SystemException { IncorrectData( std::size_t data_size, std::size_t offset, std::size_t type_size ) : data_size(data_size), offset(offset), type_size(type_size) {} std::size_t id() const noexcept { return 56; } std::pair binary() const noexcept { return { reinterpret_cast( this ), sizeof(*this) }; } const char * what() const noexcept { return "Incorrect data size"; } std::size_t data_size; std::size_t offset; std::size_t type_size; }; struct IncorrectType : public SystemException { IncorrectType( std::size_t data_size, std::size_t setting_size ) : data_size(data_size), setting_size(setting_size) {} std::size_t id() const noexcept { return 55; } std::pair binary() const noexcept { return { reinterpret_cast( this ), sizeof(*this) }; } const char * what() const noexcept { return "Incorrect setting type"; } std::size_t data_size; std::size_t setting_size; }; } /* namespace systemic */ template inline void systemic::SettingValue::set( ValueType value ) { std::lock_guard lock(data); if( value <= max and value >= min ) { std::memcpy( data.get().first + offset, reinterpret_cast( &value ), sizeof(ValueType) ); } else throw SetValueError( max, min, value ) ; } template inline ValueType systemic::SettingValue::get() const { std::shared_lock lock(data); ValueType value; std::memcpy( reinterpret_cast( &value ), data.get().first + offset, sizeof(ValueType) ); return value; } template inline systemic::SettingValue::SettingValue( systemic::SharedData data, const Constraints & constraints, std::size_t offset ) : data(data), offset(offset), min(constraints.min), max(constraints.max) { if( offset + sizeof(ValueType) > data.get().second ) throw IncorrectData( data.get().second, offset, sizeof(ValueType) ); } template inline void systemic::ConcreteSettingValue::set( ValueType value ) { std::lock_guard lock(data); if( value <= max and value >= min ) { getValue() = value; } else throw SetValueError( max, min, value ) ; } template inline ValueType systemic::ConcreteSettingValue::get() const { std::shared_lock lock(data); return getValue(); } template inline systemic::ConcreteSettingValue::ConcreteSettingValue( systemic::SharedData data, const Constraints & constraints ) : data(data), base_pointer( data.get().first ), min(constraints.min), max(constraints.max) { if( sizeof(SettingType) != data.get().second ) throw IncorrectType( data.get().second, sizeof(SettingType) ); } template inline void systemic::SettingCachedValue::set( ValueType value ) { cached = value; SettingValue::set(cached); } template inline ValueType systemic::SettingCachedValue::get() const { return cached; } template inline void systemic::SettingCachedValue::update() { cached = SettingValue::get(); } template inline systemic::SettingCachedValue::SettingCachedValue( systemic::SharedData data, const typename SettingValue::Constraints &constraints, size_t offset) : SettingValue(data, constraints, offset) {} #endif /* UMLIBRARY_SYSTEMIC_SETTINGVALUE_HH_ */