SlideShare a Scribd company logo
Использование шаблонов и RTTI
для управления конфигурацией
Григорий Цветков
Software Architect
Softeq Flash Solutions
18 Декабря, 2014
1
Коротко о себе
 Стаж в IT: 20 лет
 Стаж С++: 18 лет
 IT-тренер: 10 лет
 Области, где работает мой С++ код:
Симуляторы систем
• ФЛЭШ накопители
• 3D координатно-измерительные машины
САПР (CAD/CAM/CAE/CAx/PLM)
• Авиастроение
• Машиностроение
• Энергетика
• Метрология (высокоточные измерения)
2
 ООО «Софтек Флеш Солюшнс» зарегистрировано 24 апреля
2014 года.
 Софтек Флеш Солюшнс является частью компании SK hynix Inc.
 SK hynix занимает следующие позиции на мировом рынке:
Информация о Компании
 No. 5 Market Share in Semiconductor Industry
2014
Rank
Company
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
3
ООО «Софтек Флеш Солюшнс»
Центр Разработки SK hynix
 OOO «Софек Флеш Солюшнс» – один из шести центров
разработки (Корея, США, Япония, Италия, Беларусь, Тайвань).
US
* Global network as of Mar.31, 2014
Taiwan
Japan
Italy
Производство
Центр Продаж
Центр Разработки
Belarus
4
Разработка Встроенного Программного
Обеспечения (Firmware)
I/F SoC
(ARM, ARC)
I/F NAND
Host
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/TLC
16nm/3D
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
6
Конфигурация программного продукта
 Конфигурация программного продукта – это набор
параметров используемых приложением во время
исполнения.
 Изменение конфигурации не должно приводить к
необходимости пересобрать приложение.
 Применение конфигурации осуществляется путём
указания приложению хранилища параметров.
 Для удобства использования параметры могут
группироваться по различным признакам, группы
могут иметь любую степень вложенности.
 Приложение должно иметь простой и прозрачный
механизм для доступа к значениям параметров.
7
Требования к конфигурации симулятора флэш
накопителя
1. Простой, прозрачный и удобный доступ к любому из более
чем 2000 параметров.
2. Сложность доступа O(1).
3. Верификация:
a. Жёсткая типизация для проверки на этапе сборки.
b. Проверка по значению во время исполнения.
4. Максимально быстрая загрузка на старте.
5. Прозрачная процедура добавления/удаления параметров.
6. Возможность использовать наборы значений (массивы).
7. Возможность ссылаться на другие параметры/группы для
переключения во время исполнения.
8. Совместимость со средствами подсветки синтаксиса.
9. Независимость от сторонних программных продуктов
10. Поддержка разных форматов хранилища.
8
Обзор известных подходов к конфигурации
 Парсеры
– Плоский текст
• INI
• CSV
– Структурированные
языки с разметкой
• XML
• JSON
• YAML
 Генераторы кода
(Middleware/Binder)
– Базы данных
– XML
• Доступ к параметрам
по ключу (литералу)
• Доступ за O(1) не
гарантирован
• Добавление/удаление
параметра не видно в
исходном коде
• Требуют
использования
стороннего ПО
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;
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_; }
};
11
Выбор решения
 Требования 4 и 10 могут быть удовлетворены
путём добавления компонента сериализатора,
позволяющего работать как с бинарным дампом
структуры, так и с общепризнанными форматами
хранения структурированных данных с
поддержкой ссылок (XML, YAML).
12
Реализация
 Задачи:
1. Реализовать механизм самоописания С++ структуры в
виде дерева для того, чтобы иметь возможность обойти
всю С++ структуру не привязываясь её определению.
Фактически такое дерево есть ничто иное как DOM
(Document Object Model) известная многим, кто
сталкивался с XML.
2. Реализовать компонент-каталог, который во время
инстанциации С++ структуры описывающей
конфигурацию построит соответствующую DOM.
3. Реализовать компонент-сериализатор, позволяющий на
основании DOM сохранять/загружать конфигурации
в/из файлы/ов требуемых форматов.
4. Реализовать утилиту-приложение для генерации
эталонной (дефолтной) конфигурации и конвертации её
в различные форматы
13
Реализация
 Задача №1: «Самоописывающаяся» C++ структура
• C++ RTTI
<!> Оператор typeid позволяет получить ссылку на структуру
std::type_info, которая имеет функцию name() результатом
вызова которой будет имя типа в виде char const *.
<?> Связкаtypeid – name выдаст имя типа элемента структуры,
в то время как нам нужно имя элемента (члена данных)
структуры.
<!> Нужно имя элемента однозначно связать с типом, используя
соглашение о именовании: для простоты добавим суффикс «_t» к
имени типа, а имя элемента будем объявлять без суффикса.
<!> Все элементы в дереве параметров унаследовать либо
напрямую либо через адаптер от общего шаблонного класса,
который и будет вычислять ключ и прочие мета-данные для
элемента основе RTTI. В качестве параметра шаблона будем
передавать тип декларируемого элемента.
<???> Много букв ? Давайте смотреть код 
14
Реализация
 Демонстрационный код можно взять тут:
https://yadi.sk/d/UtFR6gXedTai3
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);
}
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; }
};
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;
}
18
Реализация
 Задача №1: «Самоописывающаяся» C++ структура
– Вывод теста:
config
config.a
config.a.b
Бинго ?!
… я тоже думаю, что босс не тот человек, которому стоит показывать
«полработы» 
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(); }
};
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;
А не многовато ли кода ради объявления одного «простого» параметра ?..
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;
}
22
Реализация
 Задача №1: «Самоописывающаяся» C++ структура
• Пробуем использовать простой параметр:
config
config.a
config.a.b
config.a.b.int_p has size 4 and value in hex is [deadbeef]
И с точки зрения разработчика моделей, который активно использует
значения параметров в коде ,всё выглядит так, как и было задумано
Придется извлечь старый магический инструмент 
Вывод теста говорит о том, что мы на верном пути
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(); }
};
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()
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;
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;
}
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 );
}
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_;
}
}
29
Реализация
 Задача №2: Каталогизатор элементов дерева параметров
• Реализация сервисов каталога:
bool register_node(i_node const & node)
{
auto ins_res = impl::dom().insert(std::ref(node));
return ins_res.second;
}
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;
}
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_;
};
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;
}
33
Реализация
 Задача №2: Каталогизатор элементов дерева параметров
• Тестируем каталогизатор:
Test catalog
Visit all from "config"
config
config.a
config.a.b
config.a.b.double_p
config.a.b.int_p
config.c
config.c.bool_p
Visit all from "config.a.b"
config.a.b
config.a.b.double_p
config.a.b.int_p
Press any key to continue . . .
34
Реализация
 Задача №3: (Сериализатор)
• По известной DOM (Document Object Model) c
доступом к каждому элементу дерева реализация
сериализатора не составит большого труда.
• Текущая реализация компонента-сериализатора
построена на XML и YAML движках с открытым
исходным кодом.
• В наших условиях не требовался перенос бинарных
форматов между различными платформами,
поэтому текущая реализация бинарной
сериализации – это просто записьчтение виз
файла потока байт, соответствующих длине
внутренних данных концевых элементов дерева.
35
Реализация
 Задача №4: (Утилита генератор/конвертор)
• Текущая реализация – это самостоятельное
приложение, использующее С++ код описания
конфигурации и сериализатор, которое в
зависимости от параметров командной строки:
Генерирует дефолтную конфигурацию в нужном
формате
Конвертирует указанную конфигурацию в требуемый
формат
36
Вопросы?
37
Спасибо за внимание!

More Related Content

PPTX
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Yandex
 
PDF
Модель памяти C++ - Андрей Янковский, Яндекс
Yandex
 
PDF
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov
 
PPTX
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Sergey Platonov
 
PDF
Антон Полухин, Немного о Boost
Sergey Platonov
 
PDF
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
PDF
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
Alexey Paznikov
 
PDF
Parallel STL
Evgeny Krutko
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Yandex
 
Модель памяти C++ - Андрей Янковский, Яндекс
Yandex
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Sergey Platonov
 
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Sergey Platonov
 
Антон Полухин, Немного о Boost
Sergey Platonov
 
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
Sergey Platonov
 
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...
Alexey Paznikov
 
Parallel STL
Evgeny Krutko
 

What's hot (20)

PDF
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Sergey Platonov
 
PPTX
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Sergey Platonov
 
PDF
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
Alexey Paznikov
 
PPTX
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
PPTX
Александр Фокин, Рефлексия в C++
Sergey Platonov
 
PPTX
Павел Беликов, Как избежать ошибок, используя современный C++
Sergey Platonov
 
PDF
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
Alexey Paznikov
 
PDF
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Platonov Sergey
 
PDF
Объектно-ориентированное программирование. Лекция 5 и 6
Dima Dzuba
 
PDF
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Yauheni Akhotnikau
 
PDF
хитрости выведения типов
corehard_by
 
PDF
Павел Довгалюк, Обратная отладка
Sergey Platonov
 
PDF
Использование юнит-тестов для повышения качества разработки
victor-yastrebov
 
PDF
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
Alexey Paznikov
 
PDF
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Dima Dzuba
 
PPTX
Современный статический анализ кода: что умеет он, чего не умели линтеры
corehard_by
 
PDF
Догнать и перегнать boost::lexical_cast
Roman Orlov
 
PDF
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Alexey Paznikov
 
PPTX
Статический анализ кода
Pavel Tsukanov
 
PDF
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
Alexey Paznikov
 
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Sergey Platonov
 
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Sergey Platonov
 
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
Alexey Paznikov
 
Никита Глушков, К вопросу о реализации кроссплатформенных фреймворков
Sergey Platonov
 
Александр Фокин, Рефлексия в C++
Sergey Platonov
 
Павел Беликов, Как избежать ошибок, используя современный C++
Sergey Platonov
 
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...
Alexey Paznikov
 
Дракон в мешке: от LLVM к C++ и проблемам неопределенного поведения
Platonov Sergey
 
Объектно-ориентированное программирование. Лекция 5 и 6
Dima Dzuba
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Yauheni Akhotnikau
 
хитрости выведения типов
corehard_by
 
Павел Довгалюк, Обратная отладка
Sergey Platonov
 
Использование юнит-тестов для повышения качества разработки
victor-yastrebov
 
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...
Alexey Paznikov
 
Объектно-Ориентированное Программирование на C++, Лекции 1 и 2
Dima Dzuba
 
Современный статический анализ кода: что умеет он, чего не умели линтеры
corehard_by
 
Догнать и перегнать boost::lexical_cast
Roman Orlov
 
Кулагин И.И., Пазников А.А., Курносов М.Г. Оптимизация информационных обменов...
Alexey Paznikov
 
Статический анализ кода
Pavel Tsukanov
 
ПВТ - весна 2015 - Лекция 3. Реентерабельность. Сигналы. Локальные данные пот...
Alexey Paznikov
 
Ad

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

PDF
C++ осень 2012 лекция 7
Technopark
 
PDF
Объектно-ориентированное программирование. Лекция 7 и 8.
Dima Dzuba
 
PDF
углубленное программирование на C++. лекция no.5 [4.0]
Technopark
 
PDF
C++ осень 2013 лекция 5
Technopark
 
PPTX
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
corehard_by
 
PDF
C++ осень 2013 лекция 8
Technopark
 
PDF
C++ Базовый. Занятие 14.
Igor Shkulipa
 
PPTX
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
Pavel Tsukanov
 
PDF
Основы С++ (операторы, типы данных, функции)
Olga Maksimenkova
 
PDF
6.4 Ещё о шаблонах
DEVTYPE
 
PDF
Дмитрий Прокопцев "Memory-mapped storage: ещё один подход к сериализации данных"
Yandex
 
PDF
Денис Чистяков: Паттерны проектирования
Yandex
 
PDF
Delphi. Профессиональное программирование
StAlKeRoV
 
PDF
Павел Артёмкин — Разработка C++ API для реализации алгоритмов на больших графах
Yandex
 
PDF
Ekb 2013 artemkin(1)
Optima-PROMO
 
PPTX
шаблоны проектирования (42)
romachka_pole
 
PDF
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
Alex V. Petrov
 
PDF
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Mail.ru Group
 
PDF
Расширение библиотеки STL для С++. Наборы и итераторы
StAlKeRoV
 
PDF
книга с++
Serghei Urban
 
C++ осень 2012 лекция 7
Technopark
 
Объектно-ориентированное программирование. Лекция 7 и 8.
Dima Dzuba
 
углубленное программирование на C++. лекция no.5 [4.0]
Technopark
 
C++ осень 2013 лекция 5
Technopark
 
Обобщенное программирование в C++ или как сделать свою жизнь проще через стра...
corehard_by
 
C++ осень 2013 лекция 8
Technopark
 
C++ Базовый. Занятие 14.
Igor Shkulipa
 
СИ++ УМЕР. ДА ЗДРАВСТВУЕТ СИ++
Pavel Tsukanov
 
Основы С++ (операторы, типы данных, функции)
Olga Maksimenkova
 
6.4 Ещё о шаблонах
DEVTYPE
 
Дмитрий Прокопцев "Memory-mapped storage: ещё один подход к сериализации данных"
Yandex
 
Денис Чистяков: Паттерны проектирования
Yandex
 
Delphi. Профессиональное программирование
StAlKeRoV
 
Павел Артёмкин — Разработка C++ API для реализации алгоритмов на больших графах
Yandex
 
Ekb 2013 artemkin(1)
Optima-PROMO
 
шаблоны проектирования (42)
romachka_pole
 
DEV Labs 2013. Can C++ Code Effeciency Be Comparable to That of Middle-Level ...
Alex V. Petrov
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Mail.ru Group
 
Расширение библиотеки STL для С++. Наборы и итераторы
StAlKeRoV
 
книга с++
Serghei Urban
 
Ad

More from Yandex (20)

PDF
Предсказание оттока игроков из World of Tanks
Yandex
 
PDF
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Yandex
 
PDF
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Yandex
 
PDF
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Yandex
 
PDF
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Yandex
 
PDF
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Yandex
 
PDF
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Yandex
 
PDF
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Yandex
 
PDF
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Yandex
 
PDF
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Yandex
 
PDF
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Yandex
 
PDF
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Yandex
 
PDF
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Yandex
 
PDF
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Yandex
 
PDF
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Yandex
 
PDF
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Yandex
 
PDF
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Yandex
 
PDF
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Yandex
 
PDF
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Yandex
 
PDF
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Yandex
 
Предсказание оттока игроков из World of Tanks
Yandex
 
Как принять/организовать работу по поисковой оптимизации сайта, Сергей Царик,...
Yandex
 
Структурированные данные, Юлия Тихоход, лекция в Школе вебмастеров Яндекса
Yandex
 
Представление сайта в поиске, Сергей Лысенко, лекция в Школе вебмастеров Яндекса
Yandex
 
Плохие методы продвижения сайта, Екатерины Гладких, лекция в Школе вебмастеро...
Yandex
 
Основные принципы ранжирования, Сергей Царик и Антон Роменский, лекция в Школ...
Yandex
 
Основные принципы индексирования сайта, Александр Смирнов, лекция в Школе веб...
Yandex
 
Мобильное приложение: как и зачем, Александр Лукин, лекция в Школе вебмастеро...
Yandex
 
Сайты на мобильных устройствах, Олег Ножичкин, лекция в Школе вебмастеров Янд...
Yandex
 
Качественная аналитика сайта, Юрий Батиевский, лекция в Школе вебмастеров Янд...
Yandex
 
Что можно и что нужно измерять на сайте, Петр Аброськин, лекция в Школе вебма...
Yandex
 
Как правильно поставить ТЗ на создание сайта, Алексей Бородкин, лекция в Школ...
Yandex
 
Как защитить свой сайт, Пётр Волков, лекция в Школе вебмастеров
Yandex
 
Как правильно составить структуру сайта, Дмитрий Сатин, лекция в Школе вебмас...
Yandex
 
Технические особенности создания сайта, Дмитрий Васильева, лекция в Школе веб...
Yandex
 
Конструкторы для отдельных элементов сайта, Елена Першина, лекция в Школе веб...
Yandex
 
Контент для интернет-магазинов, Катерина Ерошина, лекция в Школе вебмастеров ...
Yandex
 
Как написать хороший текст для сайта, Катерина Ерошина, лекция в Школе вебмас...
Yandex
 
Usability и дизайн - как не помешать пользователю, Алексей Иванов, лекция в Ш...
Yandex
 
Cайт. Зачем он и каким должен быть, Алексей Иванов, лекция в Школе вебмастеро...
Yandex
 

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

  • 1. Использование шаблонов и RTTI для управления конфигурацией Григорий Цветков Software Architect Softeq Flash Solutions 18 Декабря, 2014
  • 2. 1 Коротко о себе  Стаж в IT: 20 лет  Стаж С++: 18 лет  IT-тренер: 10 лет  Области, где работает мой С++ код: Симуляторы систем • ФЛЭШ накопители • 3D координатно-измерительные машины САПР (CAD/CAM/CAE/CAx/PLM) • Авиастроение • Машиностроение • Энергетика • Метрология (высокоточные измерения)
  • 3. 2  ООО «Софтек Флеш Солюшнс» зарегистрировано 24 апреля 2014 года.  Софтек Флеш Солюшнс является частью компании SK hynix Inc.  SK hynix занимает следующие позиции на мировом рынке: Информация о Компании  No. 5 Market Share in Semiconductor Industry 2014 Rank Company 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
  • 4. 3 ООО «Софтек Флеш Солюшнс» Центр Разработки SK hynix  OOO «Софек Флеш Солюшнс» – один из шести центров разработки (Корея, США, Япония, Италия, Беларусь, Тайвань). US * Global network as of Mar.31, 2014 Taiwan Japan Italy Производство Центр Продаж Центр Разработки Belarus
  • 5. 4 Разработка Встроенного Программного Обеспечения (Firmware) I/F SoC (ARM, ARC) I/F NAND Host 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/TLC 16nm/3D
  • 6. 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
  • 7. 6 Конфигурация программного продукта  Конфигурация программного продукта – это набор параметров используемых приложением во время исполнения.  Изменение конфигурации не должно приводить к необходимости пересобрать приложение.  Применение конфигурации осуществляется путём указания приложению хранилища параметров.  Для удобства использования параметры могут группироваться по различным признакам, группы могут иметь любую степень вложенности.  Приложение должно иметь простой и прозрачный механизм для доступа к значениям параметров.
  • 8. 7 Требования к конфигурации симулятора флэш накопителя 1. Простой, прозрачный и удобный доступ к любому из более чем 2000 параметров. 2. Сложность доступа O(1). 3. Верификация: a. Жёсткая типизация для проверки на этапе сборки. b. Проверка по значению во время исполнения. 4. Максимально быстрая загрузка на старте. 5. Прозрачная процедура добавления/удаления параметров. 6. Возможность использовать наборы значений (массивы). 7. Возможность ссылаться на другие параметры/группы для переключения во время исполнения. 8. Совместимость со средствами подсветки синтаксиса. 9. Независимость от сторонних программных продуктов 10. Поддержка разных форматов хранилища.
  • 9. 8 Обзор известных подходов к конфигурации  Парсеры – Плоский текст • INI • CSV – Структурированные языки с разметкой • XML • JSON • YAML  Генераторы кода (Middleware/Binder) – Базы данных – XML • Доступ к параметрам по ключу (литералу) • Доступ за O(1) не гарантирован • Добавление/удаление параметра не видно в исходном коде • Требуют использования стороннего ПО
  • 10. 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;
  • 11. 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_; } };
  • 12. 11 Выбор решения  Требования 4 и 10 могут быть удовлетворены путём добавления компонента сериализатора, позволяющего работать как с бинарным дампом структуры, так и с общепризнанными форматами хранения структурированных данных с поддержкой ссылок (XML, YAML).
  • 13. 12 Реализация  Задачи: 1. Реализовать механизм самоописания С++ структуры в виде дерева для того, чтобы иметь возможность обойти всю С++ структуру не привязываясь её определению. Фактически такое дерево есть ничто иное как DOM (Document Object Model) известная многим, кто сталкивался с XML. 2. Реализовать компонент-каталог, который во время инстанциации С++ структуры описывающей конфигурацию построит соответствующую DOM. 3. Реализовать компонент-сериализатор, позволяющий на основании DOM сохранять/загружать конфигурации в/из файлы/ов требуемых форматов. 4. Реализовать утилиту-приложение для генерации эталонной (дефолтной) конфигурации и конвертации её в различные форматы
  • 14. 13 Реализация  Задача №1: «Самоописывающаяся» C++ структура • C++ RTTI <!> Оператор typeid позволяет получить ссылку на структуру std::type_info, которая имеет функцию name() результатом вызова которой будет имя типа в виде char const *. <?> Связкаtypeid – name выдаст имя типа элемента структуры, в то время как нам нужно имя элемента (члена данных) структуры. <!> Нужно имя элемента однозначно связать с типом, используя соглашение о именовании: для простоты добавим суффикс «_t» к имени типа, а имя элемента будем объявлять без суффикса. <!> Все элементы в дереве параметров унаследовать либо напрямую либо через адаптер от общего шаблонного класса, который и будет вычислять ключ и прочие мета-данные для элемента основе RTTI. В качестве параметра шаблона будем передавать тип декларируемого элемента. <???> Много букв ? Давайте смотреть код 
  • 15. 14 Реализация  Демонстрационный код можно взять тут: https://yadi.sk/d/UtFR6gXedTai3
  • 16. 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); }
  • 17. 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; } };
  • 18. 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; }
  • 19. 18 Реализация  Задача №1: «Самоописывающаяся» C++ структура – Вывод теста: config config.a config.a.b Бинго ?! … я тоже думаю, что босс не тот человек, которому стоит показывать «полработы» 
  • 20. 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(); } };
  • 21. 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; А не многовато ли кода ради объявления одного «простого» параметра ?..
  • 22. 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; }
  • 23. 22 Реализация  Задача №1: «Самоописывающаяся» C++ структура • Пробуем использовать простой параметр: config config.a config.a.b config.a.b.int_p has size 4 and value in hex is [deadbeef] И с точки зрения разработчика моделей, который активно использует значения параметров в коде ,всё выглядит так, как и было задумано Придется извлечь старый магический инструмент  Вывод теста говорит о том, что мы на верном пути
  • 24. 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(); } };
  • 25. 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()
  • 26. 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;
  • 27. 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; }
  • 28. 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 ); }
  • 29. 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_; } }
  • 30. 29 Реализация  Задача №2: Каталогизатор элементов дерева параметров • Реализация сервисов каталога: bool register_node(i_node const & node) { auto ins_res = impl::dom().insert(std::ref(node)); return ins_res.second; }
  • 31. 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; }
  • 32. 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_; };
  • 33. 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; }
  • 34. 33 Реализация  Задача №2: Каталогизатор элементов дерева параметров • Тестируем каталогизатор: Test catalog Visit all from "config" config config.a config.a.b config.a.b.double_p config.a.b.int_p config.c config.c.bool_p Visit all from "config.a.b" config.a.b config.a.b.double_p config.a.b.int_p Press any key to continue . . .
  • 35. 34 Реализация  Задача №3: (Сериализатор) • По известной DOM (Document Object Model) c доступом к каждому элементу дерева реализация сериализатора не составит большого труда. • Текущая реализация компонента-сериализатора построена на XML и YAML движках с открытым исходным кодом. • В наших условиях не требовался перенос бинарных форматов между различными платформами, поэтому текущая реализация бинарной сериализации – это просто записьчтение виз файла потока байт, соответствующих длине внутренних данных концевых элементов дерева.
  • 36. 35 Реализация  Задача №4: (Утилита генератор/конвертор) • Текущая реализация – это самостоятельное приложение, использующее С++ код описания конфигурации и сериализатор, которое в зависимости от параметров командной строки: Генерирует дефолтную конфигурацию в нужном формате Конвертирует указанную конфигурацию в требуемый формат