Top Banner
Использование шаблонов и RTTI для управления конфигурацией Григорий Цветков Software Architect Softeq Flash Solutions 18 Декабря, 2014
38

Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

Jul 10, 2015

Download

Internet

Yandex
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

Использование шаблонов и RTTI для управления конфигурацией

Григорий Цветков

Software Architect

Softeq Flash Solutions

18 Декабря, 2014

Page 2: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

1

Коротко о себе

Стаж в IT: 20 лет

Стаж С++: 18 лет

IT-тренер: 10 лет

Области, где работает мой С++ код:

Симуляторы систем

• ФЛЭШ накопители

• 3D координатно-измерительные машины

САПР (CAD/CAM/CAE/CAx/PLM)

• Авиастроение

• Машиностроение

• Энергетика

• Метрология (высокоточные измерения)

Page 3: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

2

ООО «Софтек Флеш Солюшнс» зарегистрировано 24 апреля

2014 года.

Софтек Флеш Солюшнс является частью компании SK hynix Inc.

SK hynix занимает следующие позиции на мировом рынке:

Информация о Компании

No. 5 Market Share in Semiconductor Industry

2014

RankCompany

1 Intel

2 Samsung Electronics

3 Qualcomm

4 Micron Technology

5 SK hynix

6 Toshiba

7 Texas Instruments

No. 2 DRAM Market Share (2Q14)

No. 5 NAND Market Share (2Q14)

Source: iSuppli, Semiconductor Market Shares (Feb. 2014)

Source: http://www.dramexchange.com/WeeklyResearch/Post/2/3822.html

Samsung Micron

Samsung Toshiba SanDisk Micron

Page 4: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

3

ООО «Софтек Флеш Солюшнс»Центр Разработки SK hynix

OOO «Софек Флеш Солюшнс» – один из шести центров

разработки (Корея, США, Япония, Италия, Беларусь, Тайвань).

US

* Global network as of Mar.31, 2014

Taiwan

Japan

Italy

Производство

Центр Продаж

Центр Разработки

Belarus

Page 5: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

4

Разработка Встроенного Программного Обеспечения (Firmware)

I/F SoC(ARM, ARC)

I/F NANDHost

System

System-on-Chip / Система-на-кристалле Firmware / Встроенное ПО

• Host I/F Controller / Хост-контроллер

• CPU / ЦП

• RAM / ОЗУ

• NAND I/F Controller / NAND-контроллер

• Host I/F / Хост-интерфейс

• FTL (Flash Translation Layer) /

Преобразование адресов и оптимизация износа

• NAND I/F / NAND-интерфейс

Mobile Enterprise SSD Client SSD NAND Flash

eMMC/UFS SATA/SAS/PCIe SATA/PCIe SLC/MLC/TLC16nm/3D

Page 6: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

5

Преамбула

«C makes it easy to shoot yourself in the foot. C++

makes it harder, but when you do, it blows away

your whole leg.»Bjarne Stroustrup

Page 7: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

6

Конфигурация программного продукта

Конфигурация программного продукта – это набор

параметров используемых приложением во время

исполнения.

Изменение конфигурации не должно приводить к

необходимости пересобрать приложение.

Применение конфигурации осуществляется путём

указания приложению хранилища параметров.

Для удобства использования параметры могут

группироваться по различным признакам, группы

могут иметь любую степень вложенности.

Приложение должно иметь простой и прозрачный

механизм для доступа к значениям параметров.

Page 8: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

7

Требования к конфигурации симулятора флэш накопителя

1. Простой, прозрачный и удобный доступ к любому из более чем 2000 параметров.

2. Сложность доступа O(1).

3. Верификация:

a. Жёсткая типизация для проверки на этапе сборки.

b. Проверка по значению во время исполнения.

4. Максимально быстрая загрузка на старте.

5. Прозрачная процедура добавления/удаления параметров.

6. Возможность использовать наборы значений (массивы).

7. Возможность ссылаться на другие параметры/группы для переключения во время исполнения.

8. Совместимость со средствами подсветки синтаксиса.

9. Независимость от сторонних программных продуктов

10. Поддержка разных форматов хранилища.

Page 9: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

8

Обзор известных подходов к конфигурации

Парсеры

– Плоский текст

• INI

• CSV

– Структурированные языки с разметкой

• XML

• JSON

• YAML

Генераторы кода (Middleware/Binder)

– Базы данных

– XML

• Доступ к параметрам

по ключу (литералу)

• Доступ за O(1) не

гарантирован

• Добавление/удаление

параметра не видно в

исходном коде

• Требуют

использования

стороннего ПО

Page 10: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

9

Выбор решения

Первым трём требованиям (кроме 3b), a также 5-9 удовлетворяет глобальный экземпляр-синглтон С++ структуры, где для группировки параметров используются вложенные структуры:

…auto x = config.a.p1;auto y = config.b.p4;auto z = config.a.p1 + config.b.p3;…

struct config_t{

struct a_t{

int p1;bool p2;

} a;struct b_t{

int p3;bool p4;

} b;} config;

Page 11: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

10

Выбор решения

Для проверки параметров во время исполнения (требование 3b)

«концевые» элементы дерева параметров можно реализовать в виде

шаблонных классов обёрток, реализующих механизм проверки.

Аналогичный подход можно использовать для наборов (массивов).

Для ссылок можно реализовать обёртку наподобие смарт указателя.

template<typename V, typename C = std::function<bool(V)> >class param_t{

V value_;C check_;

public:param_t(V value, C check) throw(invalid_parameter_value)

: value_(value), check_(check){

if (!check_(value_))throw(invalid_parameter_value);

}T const & get() const { return value_; }

};

Page 12: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

11

Выбор решения

Требования 4 и 10 могут быть удовлетворены

путём добавления компонента сериализатора,

позволяющего работать как с бинарным дампом

структуры, так и с общепризнанными форматами

хранения структурированных данных с

поддержкой ссылок (XML, YAML).

Page 13: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

12

Реализация

Задачи:1. Реализовать механизм самоописания С++ структуры в

виде дерева для того, чтобы иметь возможность обойти всю С++ структуру не привязываясь её определению. Фактически такое дерево есть ничто иное как DOM (Document Object Model) известная многим, кто сталкивался с XML.

2. Реализовать компонент-каталог, который во время инстанциации С++ структуры описывающей конфигурацию построит соответствующую DOM.

3. Реализовать компонент-сериализатор, позволяющий на основании DOM сохранять/загружать конфигурации в/из файлы/ов требуемых форматов.

4. Реализовать утилиту-приложение для генерации эталонной (дефолтной) конфигурации и конвертации её в различные форматы

Page 14: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

13

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• C++ RTTI

<!> Оператор typeid позволяет получить ссылку на структуру std::type_info, которая имеет функцию name() результатом вызова которой будет имя типа в виде char const *.

<?> Связкаtypeid – name выдаст имя типа элемента структуры, в то время как нам нужно имя элемента (члена данных) структуры.

<!> Нужно имя элемента однозначно связать с типом, используя соглашение о именовании: для простоты добавим суффикс «_t» к имени типа, а имя элемента будем объявлять без суффикса.

<!> Все элементы в дереве параметров унаследовать либо напрямую либо через адаптер от общего шаблонного класса, который и будет вычислять ключ и прочие мета-данные для элемента основе RTTI. В качестве параметра шаблона будем передавать тип декларируемого элемента.

<???> Много букв ? Давайте смотреть код

Page 15: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

14

Реализация

Демонстрационный код можно взять тут:

https://yadi.sk/d/UtFR6gXedTai3

Page 16: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

15

Реализация

Задача №1: «Самоописывающаяся» C++ структура

/** Интерфейс элемента дерева параметров. */struct i_node{

virtual size_t size() const = 0;virtual node_id const & key() const = 0;

};

namespace details{

/** Предварительное объявление преобразователя ключа */node_id compute_id(char const * type_name);/** Оператор вывода*/template<typename TOStream>TOStream & operator << (TOStream & ostream, node_id const & id);

}

Page 17: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

16

Реализация

Задача №1: «Само-описывающаяся» C++ структура

/** Базовая структура вычисляющая ключ на основе RTTI */template<typename TNodeImpl>struct node : i_node{

node_id const & key() const override{

if (id_.empty())id_ = std::move(details::compute_id(typeid(TNodeImpl).name()));

return id_;}

private:mutable node_id id_;

};

/** Базовая структура для группы параметров */template<typename TNodeImpl>struct group : node<TNodeImpl>{

size_t size() const override { return 0; }};

Page 18: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

17

Реализация

Задача №1: «Само-описывающаяся» C++ структура

namespace cfg = config_framework;

struct config_t : cfg::group<config_t>{

struct a_t : cfg::group<a_t>{

struct b_t : cfg::group<b_t>{} b;

} a;} config;

int _tmain(int argc, _TCHAR* argv[]){

using namespace std;cout << config.key() << endl;cout << config.a.key() << endl;cout << config.a.b.key() << endl;return 0;

}

Page 19: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

18

Реализация

Задача №1: «Самоописывающаяся» C++ структура

– Вывод теста:

configconfig.aconfig.a.b

Бинго ?!

… я тоже думаю, что босс не тот человек, которому стоит показывать«полработы»

Page 20: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

19

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Реализация обёртки для параметра конфигурации:/** Обёртка для значения параметра */template<typename TParamValue>struct value_wrapper{

explicit value_wrapper(TParamValue value) : value_(value) {}operator TParamValue const & () const { return value_; }TParamValue const & get() const { return value_; }

protected:size_t size() const { return sizeof value_; }

protected:TParamValue value_;

};

/** Базовая структура простого параметра */template<typename TParamValue, typename TParamImpl>struct simple_param : value_wrapper<TParamValue>, node<TParamImpl>{

explicit simple_param(TParamValue value): value_wrapper<TParamValue>(value) {}

size_t size() const override { return value_wrapper<TParamValue>::size(); }};

Page 21: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

20

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Пробуем использовать простой параметр:

namespace cfg = config_framework;

struct config_t : cfg::group<config_t>{

struct a_t : cfg::group<a_t>{

struct b_t : cfg::group<b_t>{

struct int_p_t : cfg::simple_param<int, int_p_t>{

int_p_t() : cfg::simple_param<int, int_p_t>(0xDEADBEEF) {}} int_p;

} b;} a;

} config;

А не многовато ли кода ради объявления одного «простого» параметра ?..

Page 22: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

21

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Пробуем использовать простой параметр:

int _tmain(int argc, _TCHAR* argv[]){

using namespace std;cout << config.key() << endl;cout << config.a.key() << endl;cout << config.a.b.key() << endl;cout << config.a.b.int_p.key()

<< " has size " << config.a.b.int_p.size()<< " and value in hex is [" << hex << config.a.b.int_p << "]"<< endl;

return 0;}

Page 23: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

22

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Пробуем использовать простой параметр:

configconfig.aconfig.a.bconfig.a.b.int_p has size 4 and value in hex is [deadbeef]

И с точки зрения разработчика моделей, который активно использует значения параметров в коде ,всё выглядит так, как и было задумано

Придется извлечь старый магический инструмент

Вывод теста говорит о том, что мы на верном пути

Page 24: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

23

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Упрощаем жизнь разработчикам:

/** Базовая структура простого параметра */template<typename TParamValue, typename TParamImpl>struct simple_param : value_wrapper<TParamValue>, node<TParamImpl>{

/** Алиас для имени типа */typedef simple_param<TParamValue, TParamImpl> base_impl_type;explicit simple_param(TParamValue value)

: value_wrapper<TParamValue>(value) {}size_t size() const override { return value_wrapper<TParamValue>::size(); }

};

Page 25: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

24

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Упрощаем жизнь разработчикам

/** Макрос получения типа по имени типа элемента дерева. */#define guess_type(name) name##_t

/** Макрос для декларации простого параметра. */#define declare_simple_param(param_name,value_type,param_value) \

struct guess_type(param_name) \: config_framework::simple_param \

< value_type \, guess_type(param_name) > \

{ \guess_type(param_name)() : base_impl_type(param_value) {} \

} param_name \// end of macro: declare_simple_param()

Page 26: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

25

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Упрощаем жизнь разработчикам:

namespace cfg = config_framework;

struct config_t : cfg::group<config_t>{

struct a_t : cfg::group<a_t>{

struct b_t : cfg::group<b_t>{

declare_simple_param(int_p, int, 0xDEADBEEF);declare_simple_param(double_p, double, 1.1E-11);

} b;} a;struct c_t : cfg::group<c_t>{

declare_simple_param(bool_p, bool, true);} c;

} config;

Page 27: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

26

Реализация

Задача №1: «Самоописывающаяся» C++ структура

• Упрощаем жизнь разработчикам:

int _tmain(int argc, _TCHAR* argv[]){

using namespace std;cout << config.key() << endl;cout << config.a.key() << endl;cout << config.a.b.key() << endl;cout << config.a.b.int_p.key()

<< " has size " << config.a.b.int_p.size()<< " and value in hex is [" << hex << config.a.b.int_p << "]"<< endl;

cout << config.a.b.double_p.key()<< " has size " << config.a.b.double_p.size()<< " and value is [" << config.a.b.double_p << "]"<< endl;

cout << config.c.bool_p.key()<< " has size " << config.c.bool_p.size()<< " and value is [" << boolalpha << config.c.bool_p << "]"<< endl;

return 0;}

Page 28: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

27

Реализация

Задача №2: Каталогизатор элементов дерева параметров• Служебный компонент, реализующий каталог связей

элементов дерева параметров с идентификаторами, которые используются во внешнем хранилище.

namespace catalog{

/** Регистрация элемента дерева параметров. */bool register_node(i_node const & node);/** Действие, применяемое обходе дерева параметров. */typedef std::function<bool(i_node & node)> node_visitor;/** Результат обхода ветви дерева параметров. */typedef std::pair<size_t, bool> visit_result;/** Обхода дерева параметров. */visit_result visit_children

( i_node const & node, node_visitor visitor );

}

Page 29: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

28

Реализация

Задача №2: Каталогизатор элементов дерева параметров

• Скрытая реализация DOM:

namespace impl{

typedef std::reference_wrapper<i_node const> node_ref;struct node_ref_less

: std::binary_function<node_ref, node_ref, bool>{

bool operator()( node_ref left

, node_ref right ){

return ( left.get().key() < right.get().key() );}

};typedef std::set<node_ref, node_ref_less> dom_t;dom_t & dom(){

static dom_t dom_;return dom_;

}}

Page 30: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

29

Реализация

Задача №2: Каталогизатор элементов дерева параметров

• Реализация сервисов каталога:

bool register_node(i_node const & node){

auto ins_res = impl::dom().insert(std::ref(node));return ins_res.second;

}

Page 31: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

30

Реализация

visit_result visit_children( i_node const & node

, node_visitor visitor){

visit_result res = { 0, true };auto const & key = node.key();auto const idx = key.size() - 1;auto it_cat = impl::dom().lower_bound(std::ref(node));auto const & end = impl::dom().end();auto check_visit_condition = [&]()->bool{

if (end == it_cat)return false;

auto const & current_key = it_cat->get().key();if (idx >= current_key.size())

return false;return (key[idx] == current_key[idx]);

};for (; check_visit_condition(); ++it_cat, ++res.first)

if (!visitor(const_cast<i_node&>(it_cat->get()))){

res.second = false;break;

}return res;

}

Page 32: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

31

Реализация

Задача №2: Каталогизатор элементов дерева параметров

• Модификации для работы с каталогом:

/** Базовая структура вычисляющая ключ на основе RTTI */template<typename TNodeImpl>struct node : i_node{

node_id const & key() const override{

return id_;}node() : id_( std::move(details::compute_id(typeid(TNodeImpl).name())) ){

catalog::register_node(*this);}

private:mutable node_id id_;

};

Page 33: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

32

Реализация

Задача №2: Каталогизатор элементов дерева параметров

• Тестируем каталогизатор:

int _tmain(int argc, _TCHAR* argv[]){

using namespace std;cout << "Visit all from \"" << config.key() << "\"" << endl;auto vr1 = cfg::catalog::visit_children

( config, [](cfg::i_node & node)->bool{

cout << node.key() << endl;return true;

} );cout << "Visit all from \"" << config.a.b.key() << "\"" << endl;auto vr2 = cfg::catalog::visit_children

( config.a.b, [](cfg::i_node & node)->bool{

cout << node.key() << endl;return true;

} );return 0;

}

Page 34: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

33

Реализация

Задача №2: Каталогизатор элементов дерева параметров

• Тестируем каталогизатор:

Test catalogVisit all from "config"configconfig.aconfig.a.bconfig.a.b.double_pconfig.a.b.int_pconfig.cconfig.c.bool_pVisit all from "config.a.b"config.a.bconfig.a.b.double_pconfig.a.b.int_pPress any key to continue . . .

Page 35: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

34

Реализация

Задача №3: (Сериализатор)

• По известной DOM (Document Object Model) c

доступом к каждому элементу дерева реализация

сериализатора не составит большого труда.

• Текущая реализация компонента-сериализатора

построена на XML и YAML движках с открытым

исходным кодом.

• В наших условиях не требовался перенос бинарных

форматов между различными платформами,

поэтому текущая реализация бинарной

сериализации – это просто запись\чтение в\из

файл\а потока байт, соответствующих длине

внутренних данных концевых элементов дерева.

Page 36: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

35

Реализация

Задача №4: (Утилита генератор/конвертор)

• Текущая реализация – это самостоятельное

приложение, использующее С++ код описания

конфигурации и сериализатор, которое в

зависимости от параметров командной строки:

Генерирует дефолтную конфигурацию в нужном

формате

Конвертирует указанную конфигурацию в требуемый

формат

Page 37: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

36

Вопросы?

Page 38: Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Григорий Цветков. Softeq Flash

37

Спасибо за внимание!