Начал чесать репу на тему создания такого mchain-а или mbox-а для SObjectizer-а, который бы позволил двум SObjectizer-приложениям на одной ноде взаимодействовать друг с другом через разделяемую память. Беглый поиск по Интернету показал, что выбор инструментов для этой задачи сравнительно небольшой: либо придется делать свой собственный велосипед, либо же нужно брать что-то из Boost, ACE, POCO или чего-то сравнимого по размеру.
Писать свой лисапед не захотелось, тем более, что сперва нужно сделать какой-то прототип нового mchain-а, ибо на данный момент реализация такого mchain-а выглядит как сплошное белое пятно. Хочется без лишних проволочек начать работать над прототипом, а уже потом, когда прототип заработает, решать, что же делать дальше.
Решил попробовать Boost.Interprocess. Но т.к. с "большим" Boost-ом иметь дело не хочется, то попробовал подтащить в небольшой демо-проектик Boost.Interprocess и все его зависимости из "модульного" Boost-а, который нынче доступен на github-е.
Методом проб и ошибок это удалось сделать (в очередной раз скажу, что Boost в виде большой говнопомойки не нужен и должен быть разрушен). Результат можно увидеть в этом репозитории. Ниже чуть-чуть прокомментирую то, что получилось.
Итак, нужно было решить три проблемы (ну или задачи, т.к. что-то из перечисленного точно проблемой не является).
Во-первых, нужно получить список Boost-овых "модулей", которые нужны для Boost.Interprocess. Что оказалось не совсем просто, т.к. удобного способа узнать полный список зависимостей конкретного "модуля" я не нашел. Boostdep, при простом его использовании, выдает только прямые зависимости, но не перечисляет косвенные. В общем, здесь все решилось экспериментальным путем и парой-тройкой обращений к Boostdep.
Во-вторых, нужно было сделать список Boost-овых "модуле" в файле externals.rb. Естественно, что когда этот список стал приобретать вид сплошной копипасты:
MxxRu::arch_externals :boost_assert do |e| e.url 'https://github.com/boostorg/assert/archive/boost-1.67.0.zip' e.map_dir 'include/boost' => 'dev/boostorg/assert' end MxxRu::arch_externals :boost_config do |e| e.url 'https://github.com/boostorg/config/archive/boost-1.67.0.zip' e.map_dir 'include/boost' => 'dev/boostorg/config' end MxxRu::arch_externals :boost_container do |e| e.url 'https://github.com/boostorg/container/archive/boost-1.67.0.zip' e.map_dir 'include/boost' => 'dev/boostorg/container' end ... |
То захотелось этот объем сократить. Сперва по такому пути:
BOOST_GITHUB_PREFIX = 'https://github.com/boostorg' BOOST_VER = '1.67.0' MxxRu::arch_externals :boost_assert do |e| e.url "#{BOOST_GITHUB_PREFIX}/assert/archive/boost-#{BOOST_VER}.zip" e.map_dir "include/boost" => "dev/boostorg/assert" end MxxRu::arch_externals :boost_config do |e| e.url "#{BOOST_GITHUB_PREFIX}/config/archive/boost-#{BOOST_VER}.zip" e.map_dir "include/boost" => "dev/boostorg/config" end MxxRu::arch_externals :boost_container do |e| e.url "#{BOOST_GITHUB_PREFIX}/container/archive/boost-#{BOOST_VER}.zip" e.map_dir "include/boost" => "dev/boostorg/container" end ... |
Поэтому был принят еще более радикальный способ сокращения копипасты:
BOOST_GITHUB_PREFIX = 'https://github.com/boostorg' BOOST_VER = '1.67.0' BOOST_MODULES = %w{ assert config container container_hash core date_time detail functional integer interprocess intrusive move mpl numeric_conversion predef preprocessor smart_ptr static_assert throw_exception tuple type_traits unordered utility winapi } BOOST_MODULES.each do |md| key = "boost_#{md}".to_sym MxxRu::arch_externals key do |e| e.url "#{BOOST_GITHUB_PREFIX}/#{md}/archive/boost-#{BOOST_VER}.zip" e.map_dir "include/boost" => "dev/boostorg/#{md}" end end |
Т.е. создавался массив имен "модулей" из Boost-а, в итерации по которому затем и строился список зависимостей для MxxRu.
В-третьих, в файле build.rb нужно было задать пути для поиска заголовочных файлов "модулей" из Boost-а. Перечислять их все вручную было не интересно. Поэтому сперва была сделана вот такая попытка: определение BOOST_MODULES со списком "модулей" было помещено в отдельный файл boost_modules.rb. Этот файл затем подключался в externals.rb и в build.rb.
Но такой поход оказался несовместим с логикой работы MxxRu::externals. Для MxxRu::externals нужно, чтобы вся информация о зависимостях описывалась в externals.rb. Тогда при изменении externals.rb можно определить что именно изменилось, а что осталось прежним. Но если актуальный список модулей лежит не в externals.rb, а в boost_modules.rb, то MxxRu::externals не может отследить модификацию boost_modules.rb и, например, при удалении какого-то модуля из списка исходники этого модуля из рабочего каталога MxxRu::externals не удалит.
Поэтому было сделано так, что файл boost_modules.rb генерируется при обработке externals.rb. Для чего в externals.rb цикл по списку модулей был переписан следующим образом:
File.open('dev/_boost_modules_list.rb', 'w') do |f| f << "BOOST_MODULES = %w{\n" BOOST_MODULES.each do |md| f << " #{md}\n" key = "boost_#{md}".to_sym MxxRu::arch_externals key do |e| e.url "#{BOOST_GITHUB_PREFIX}/#{md}/archive/boost-#{BOOST_VER}.zip" e.map_dir "include/boost" => "dev/boostorg/#{md}" end end f << "}" end |
Вот в таком виде при запуске утилиты mxxruexternals все нужные зависимости подгружаются с github-а и это делает возможным дальнейшую сборку демо-проекта без установки всего Boost-а непосредственно в систему. Что и было проверено под Windows, Linux (Ubuntu 16.04) и FreeBSD 10.3.
Так что эксперимент завершился успешно, но остаточек остался. Ну и соблазн сделать свой инструмент для работы с shared memory вместо Boost.Interprocess (в зависимостях которого обнаружился даже MPL), стал практически непреодолимым.
Комментариев нет:
Отправить комментарий