236 lines
6.6 KiB
C++
236 lines
6.6 KiB
C++
/*
|
||
* 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 <cstring>
|
||
#include <mutex>
|
||
#include <shared_mutex>
|
||
|
||
#include "SystemException.hh"
|
||
|
||
namespace systemic {
|
||
|
||
//! Класс реализует интерфейс доступа к полю настройки.
|
||
template<typename ValueType>
|
||
class SettingValue : public IValueType<ValueType> {
|
||
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<typename ValueType>
|
||
class SettingCachedValue : public SettingValue<ValueType> {
|
||
|
||
ValueType cached;
|
||
|
||
public:
|
||
void set( ValueType value );
|
||
ValueType get() const;
|
||
|
||
void update();
|
||
|
||
SettingCachedValue( systemic::SharedData data, const typename SettingValue<ValueType>::Constraints & constraints, size_t offset );
|
||
|
||
};
|
||
|
||
//! Шаблонная версия класса для доступа к полю настройки.
|
||
template<typename SettingType, typename ValueType, ValueType (SettingType::*member_p)>
|
||
struct ConcreteSettingValue : public IValueType<ValueType> {
|
||
private:
|
||
mutable systemic::SharedData data;
|
||
char * const base_pointer;
|
||
|
||
ValueType & getValue() { return ( reinterpret_cast<SettingType*>(base_pointer) )->*member_p; }
|
||
ValueType & getValue() const { return ( reinterpret_cast<SettingType*>(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<const char *, std::size_t> binary() const noexcept { return {reinterpret_cast<const char *>( 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<const char *, std::size_t> binary() const noexcept { return { reinterpret_cast<const char *>( 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<const char *, std::size_t> binary() const noexcept { return { reinterpret_cast<const char *>( 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<typename ValueType>
|
||
inline void systemic::SettingValue<ValueType>::set( ValueType value ) {
|
||
|
||
std::lock_guard<systemic::SharedData> lock(data);
|
||
|
||
if( value <= max and value >= min ) {
|
||
std::memcpy( data.get().first + offset, reinterpret_cast<char *>( &value ), sizeof(ValueType) );
|
||
} else
|
||
throw SetValueError( max, min, value ) ;
|
||
|
||
}
|
||
|
||
template<typename ValueType>
|
||
inline ValueType systemic::SettingValue<ValueType>::get() const {
|
||
|
||
std::shared_lock<systemic::SharedData> lock(data);
|
||
|
||
ValueType value;
|
||
|
||
std::memcpy( reinterpret_cast<char *>( &value ), data.get().first + offset, sizeof(ValueType) );
|
||
|
||
return value;
|
||
}
|
||
|
||
template<typename ValueType>
|
||
inline systemic::SettingValue<ValueType>::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<typename SettingType, typename ValueType,
|
||
ValueType (SettingType::*member_p)>
|
||
inline void systemic::ConcreteSettingValue<SettingType, ValueType, member_p>::set(
|
||
ValueType value ) {
|
||
|
||
std::lock_guard<systemic::SharedData> lock(data);
|
||
|
||
if( value <= max and value >= min ) {
|
||
getValue() = value;
|
||
} else
|
||
throw SetValueError( max, min, value ) ;
|
||
|
||
}
|
||
|
||
template<typename SettingType, typename ValueType,
|
||
ValueType (SettingType::*member_p)>
|
||
inline ValueType systemic::ConcreteSettingValue<SettingType, ValueType, member_p>::get() const {
|
||
|
||
std::shared_lock<systemic::SharedData> lock(data);
|
||
|
||
return getValue();
|
||
|
||
}
|
||
|
||
template<typename SettingType, typename ValueType,
|
||
ValueType (SettingType::*member_p)>
|
||
inline systemic::ConcreteSettingValue<SettingType, ValueType, member_p>::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<typename ValueType>
|
||
inline void systemic::SettingCachedValue<ValueType>::set( ValueType value ) {
|
||
|
||
cached = value;
|
||
|
||
SettingValue<ValueType>::set(cached);
|
||
|
||
}
|
||
|
||
template<typename ValueType>
|
||
inline ValueType systemic::SettingCachedValue<ValueType>::get() const {
|
||
|
||
return cached;
|
||
|
||
}
|
||
|
||
template<typename ValueType>
|
||
inline void systemic::SettingCachedValue<ValueType>::update() {
|
||
|
||
cached = SettingValue<ValueType>::get();
|
||
|
||
}
|
||
|
||
template<typename ValueType>
|
||
inline systemic::SettingCachedValue<ValueType>::SettingCachedValue(
|
||
systemic::SharedData data, const typename SettingValue<ValueType>::Constraints &constraints,
|
||
size_t offset) : SettingValue<ValueType>(data, constraints, offset) {}
|
||
|
||
#endif /* UMLIBRARY_SYSTEMIC_SETTINGVALUE_HH_ */
|