LINUX.ORG.RU

Обновился инструмент для работы с агентами в C++: SObjectizer 5.5.8

 , , ,


0

3

SObjectizer — это небольшой фреймворк для упрощения разработки многопоточных приложений на C++ за счет организации асинхронного обмена сообщениями между объектами-агентами.

Проект живет на SourceForge, распространяется под трехпунктной BSD-лицензией.

Версию 5.5.8 можно взять либо из секции Files на SF, либо из Svn-репозитория, либо из зеркала на GitHub.

Если говорить кратко, то в версии 5.5.8 появилось следующее:

  • приоритеты у агентов и три новых диспетчера, которые выполняют обработку событий с учетом приоритетов;
  • более удобные средства работы с ad-hoc агентами;
  • несколько новых примеров.

Если интересны подробности, то сюда, либо сюда, либо сюда.

Краткую информацию о том, что такое SObjectizer можно найти здесь и далее по ссылкам.

★★★★★

Ответ на: комментарий от eao197

не спросить, а констатировать. первая фича, без которой поделка серьёзно рассматриваться не может — возможность написания диспетчеров под особенности приложения.

anonymous
()
Ответ на: комментарий от anonymous

возможность написания диспетчеров под особенности приложения.

Ну и кто вам сказал, что такой возможности нет? Делаете своих наследников для dispatcher_t и disp_binder_t, подсовываете их SO Run-Time и полный вперед.

eao197 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Рантайм обеспечивает запуск и останов того хозяйства, которое нужно для работы: нить обслуживания таймеров, нить дерегистрации, публичные диспетчеры, пользовательские layer-ы и т.д.

Непосредственная диспетчеризация заявок выполняется посредством диспетчеров, каждый из которых поддерживает какой-то свой уникальный режим обслуживания заявок.

Кухня приблизительно такая:

  • диспетчер создает рабочие нити, на которых будет происходить обслуживание заявок;
  • когда агент добавляется в работающий Run-Time, агенту назначается disp_binder (т.е. объект, который знает, как привязать агента к конкретному типу диспетчера);
  • во время регистрации агента дергается его disp_binder, который говорит нужному диспетчеру: «у тебя появился еще один агент, дайка мне event_queue для него». Диспетчер отдает указатель на event_queue, и этот указатель фиксируется внутри агента. Что будет скрываться за данным указателем (отдельная очередь для каждого агента, общая очередь для всех агентов, очередь на какую-то группу агентов и т.д.) — это уже внутреннее дело каждого типа диспетчера;
  • при отсылке сообщения идет перебор всех подписчиков, у каждого подписчика берется ссылка на его event_queue и туда запихивается заявка на обработку сообщения;
  • т.е. event_queue — это просто мостик к потрохам диспетчера, то, фактически, заявку получает диспетчер, к которому привязали агента. Этот диспетчер уже решает, что и как сделать с заявкой.
  • при дерегистрации агента еще раз дергается disp_binder, но в этот раз уже для отвязки агента от диспетчера. Disp_binder говорит диспетчеру: «У тебя больше этого агента нет, очисти все ресурсы с ним связанные».

В общих чертах как-то так. Поэтому, фактически, создание диспетчера — это разработка уникальной пары из dispatcher_t и disp_binder_t. Плюс, если у них какая-то хитрая схема обслуживания заявок (как в двух новых prio_one_thread-диспетчерах), то у них будет еще и собственная реализация event_queue_t.

eao197 ★★★★★
() автор топика

Ура! Когда-нить я это обязательно попробую. Вот только не могу придумать где. Обычно Asio хватает :-/

anonymous
()
Ответ на: комментарий от anonymous

Вот только не могу придумать где. Обычно Asio хватает :-/

Asio, имхо, все-таки для немного других задач. На Asio, например, можно реализовать клиента к какому-нибудь MQ (будь то AMQP или Kafka). Написанная на Asio часть будет работать с каналами, парсить прочитанные данные, отправлять исходящие и т.д. Но вот дальше же должна быть какая-то прикладная обработка. Есть поток каких-то прикладных сообщений, этот поток нужно обработать. Тут-то агенты и начинают хорошо работать.

eao197 ★★★★★
() автор топика

Между процессами сообщения умеет слать? Как у него с переносимостью. Как насчет других языков (например, :два процесса на плюсах и питоне должны взаимодействовать)

invy ★★★★★
()
Ответ на: комментарий от eao197

Asio часть будет работать с каналами, парсить прочитанные данные,

Ну в асио есть io_service, в который можно вызовы складывать.

Есть поток каких-то прикладных сообщений, этот поток нужно обработать.

Воот. Есть поток, который вертит io_service, который исполняет вызовы. А если пользовать promise и future так исполнение конкретного вызова и дождаться можно.

anonymous
()
Ответ на: как сложно-то от anonymous

Может вам таки с инструментом ознакомиться в конце концов?

А то сначала «как собственный диспетчер сделать?», а потом «как сложно-то». Уже есть восемь готовых диспетчеров из коробки. Если не хватает, можете свой дописать.

eao197 ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Ну в асио есть io_service, в который можно вызовы складывать.

Ну и замечательно. Если функциональности io_service хватает, то зачем использовать что-то еще?

eao197 ★★★★★
() автор топика
Ответ на: комментарий от eao197

зачем?

1. сложно то, что у нормальных людей диспетчер — это такой же актёр, с той лишь разницей, что его можно явно запустить и остановить.

2. если не хватает... то я не припомню 2 неигрушечные задачи для которых использовал бы один и тот же диспетчер.

anonymous
()
Ответ на: комментарий от anonymous

зачем?

Чтобы говорить более-менее по теме.

eao197 ★★★★★
() автор топика
Ответ на: комментарий от invy

Если вам нужно общение плюсовых компонентов с питоньими, то уже полно готовых инструментов или заготовок для них. Можно хоть свой протокол на базе Protobuf-а или Thrif-а написать, можно использовать готовые вещи, вроде ZeroC Ice или, прасти хосподя, CORBA, с целой кучей готовых MQ-шных вещей посередине.

Если хочется готового интеропа между двумя плюсовыми компонентами по какому-то чужому протоколу не понятного качества, то есть C++ Actor Framework, там это из коробки.

eao197 ★★★★★
() автор топика

LOL :)

И опять никому не нужный фреймворк

CyberK
()

Тред очередного сеанса борьбы с ветряными мельницами)

anonymous
()

Да что за чушь в комментариях? Человек вырастил, например, яблоню и собрал с него яблок. Выставил за дом с табличкой «Угощайтесь»! Подходят анонимы и начинают ныть: «яблоки не нужны», «а я больше груши люблю», «а мне больше зеленые нравятся» и т.д. Не хотите яблок? Проходите мимо! Если вам они не нужны, это не значит, что они не нужны другому. Хотите чтобы в следующий раз яблоки были как раз такими, как вам нравится? Так хозяин готов выслушать ваши замечания и, быть может, в следующем году яблоки будут как раз такие, какие вам нужны.

anonymous
()

Вроде хорошая вещь, единственно, может стоит в примерах использовать using namespace? А то уж слишком много so_5::rt::. Без них примеры выглядели бы проще.

anonymous
()
Ответ на: комментарий от anonymous

А то уж слишком много so_5::rt::

Да с удовольствием бы, но тогда doxygen лажает с определением имен и может либо вообще не делать связи между примером и документацией, либо же делает неправильные связи.

eao197 ★★★★★
() автор топика

Может быть кого-то из читателей темы заинтересует: вот здесь дано описание нового примера, который показывает, для чего может потребоваться создавать несколько экземпляров SO Environment внутри одного приложения, и как это может выглядеть.

eao197 ★★★★★
() автор топика

Можно комментарий?

 [ ~ ] $ mkdir /tmp/so
 [ ~ ] $ cd /tmp/so
 [ /tmp/so ] $ wget -q https://github.com/masterspline/SObjectizer/archive/v5.5.8.tar.gz && echo "done"
done
 [ /tmp/so ] $ tar xf v5.5.8.tar.gz 
 [ /tmp/so ] $ mkdir build
 [ /tmp/so ] $ cd build/
 [ /tmp/so/build ] $ cmake -DBUILD_ALL=ON ../SObjectizer-5.5.8/dev/
-- The C compiler identification is GNU 4.9.3
-- The CXX compiler identification is GNU 4.9.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/so/build
 [ /tmp/so/build ] $ make
Scanning dependencies of target so.5.5.8
[  0%] Building CXX object so_5/CMakeFiles/so.5.5.8.dir/exception.cpp.o
[  1%] Building CXX object so_5/CMakeFiles/so.5.5.8.dir/current_thread_id.cpp.o
[  1%] Building CXX object so_5/CMakeFiles/so.5.5.8.dir/atomic_refcounted.cpp.o
[  1%] Building CXX object so_5/CMakeFiles/so.5.5.8.dir/error_logger.cpp.o
[  1%] Building CXX object so_5/CMakeFiles/so.5.5.8.dir/timers.cpp.o
/tmp/so/SObjectizer-5.5.8/dev/so_5/timers.cpp:15:27: фатальная ошибка: timertt/all.hpp: Нет такого файла или каталога
 #include <timertt/all.hpp>
                           ^
компиляция прервана.                                                                                                                                                                                 
so_5/CMakeFiles/so.5.5.8.dir/build.make:158: ошибка выполнения рецепта для цели «so_5/CMakeFiles/so.5.5.8.dir/timers.cpp.o»                                                                          
make[2]: *** [so_5/CMakeFiles/so.5.5.8.dir/timers.cpp.o] Ошибка 1                                                                                                                                    
CMakeFiles/Makefile2:85: ошибка выполнения рецепта для цели «so_5/CMakeFiles/so.5.5.8.dir/all»                                                                                                       
make[1]: *** [so_5/CMakeFiles/so.5.5.8.dir/all] Ошибка 2                                                                                                                                             
Makefile:138: ошибка выполнения рецепта для цели «all»                                                                                                                                               
make: *** [all] Ошибка 2                                                                                                                                                                             
 [ /tmp/so/build ] $ tree -L 2 /tmp/so/SObjectizer-5.5.8/dev/
/tmp/so/SObjectizer-5.5.8/dev/
├── build_all.rb
├── build.rb
├── cmake
│   ├── CmakeQuickHowto.txt
│   └── run_tests.bat
├── CMakeLists.txt
├── sample
│   └── so_5
├── so_5
│   ├── all.hpp
│   ├── api
│   ├── atomic_refcounted.cpp
│   ├── CMakeLists.txt
│   ├── current_thread_id.cpp
│   ├── details
│   ├── disp
│   ├── error_logger.cpp
│   ├── exception.cpp
│   ├── h
│   ├── prj.rb
│   ├── rt
│   ├── timers.cpp
│   ├── version.dox
│   └── version.rb
├── test
│   └── so_5
├── timertt
├── utest_helper_1
└── various_helpers_1

14 directories, 15 files
 [ /tmp/so/build ] $ 
Stil ★★★★★
()
Ответ на: комментарий от Stil

Окей, нашел это, но, блджад, я внимательно прочитал README, и там не было упоминаний этой зависимости. Хелперы тоже руками тащить?)

Stil ★★★★★
()
Ответ на: комментарий от anonymous

ааа, там ваще файлов нету. Тогдаясно.

anonymous
()
Ответ на: комментарий от Stil

В README на github-е указан перечень команд для сборки:

git clone --recursive https://github.com/masterspline/SObjectizer.git so
mkdir build
cd build
cmake -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=installed_files ../so/dev
make
make test
make install
Поскольку зависимости подтягиваются через git submodules, то, вероятно, если вы тянете tar.gz файл с гитхаба, то в нем этих зависимостей нет. Если делаете git clone --recursive, то должны подтянуться.

PS. Вообще, зеркало на GH поддерживаю не я и с GH не работаю, то переадресую эту проблему владельцу зеркала. Если хотите взять готовые исходники без плясок с бубном, то забрать их можно с SF.

eao197 ★★★★★
() автор топика
Последнее исправление: eao197 (всего исправлений: 1)
Ответ на: комментарий от Stil

На самом деле вы не первый, кто не делает git clone --recursive, в результате не получает трех подпроектов и сообщает мне об ошибке, хотя это написано в самом начале README.md. В общем, если сможешь объяснить мне, как предотвратить такое в дальнейшем, будет замечательно.

prefetch
()
Ответ на: комментарий от Stil

Короткий ответ такой: с гитхаба не нужно брать архивы исходников, нужно клонировать репозиторий, как написано в README.md на github.

Тут ситуация такая: изначальный проект сделан на svn, в котором есть довольно удобная штука svn::externals, в гит полного аналога нет, поэтому я это эмулировал через git::submodules, и эти submodules идут отдельными репозиториями. В результате, если брать архивы с гитхаба, то нужно брать сам SObjectizer и все три его подпроекта. Это жутко неудобно, поэтому проще клонировать весь репозиторий, причем либо git clone --recursive, как указано в README.md на гитхабе, либо отдельной командой обновить submodules. Если хочется получить только последнюю версию исходников без истории, то можно добавить --depth 1 к команде клонирования.

git clone --recursive --depth 1 https://github.com/masterspline/SObjectizer.git so

Если вам нужен именно архив исходников вместе с подпроектами, то его можно взять на SourceForge. Если почему-то удобнее брать архив с гитхаба, то отпишите чуть подробнее, чтобы я смог понять, как это удобнее сделать.

prefetch
()
Ответ на: комментарий от prefetch

На самом деле вы не первый, кто не делает git clone --recursive, в результате не получает трех подпроектов и сообщает мне об ошибке, хотя это написано в самом начале README.md.

Но ведь поинт тарболов именно в том, чтобы скачать архив и пользоваться. Если бы я хотел тащить с гита — я бы конечно прочитал бы README.md и сделал бы git clone --recursive.

В общем, если сможешь объяснить мне, как предотвратить такое в дальнейшем, будет замечательно.

Я не знаю. Вот например в описании timertt на SF написано

timertt (Timer Thread Template) is a small, template based, header only library for C++11. It implements timer threads: thread which handles timers. timertt has no external dependecies except standard C++11 library. timertt was developed as part of SObjectizer[1] project but can be used as standalone library.

Т.е. чисто теоретически оно может использоваться отдельно — тогда можно прописать её как внешнюю зависимость.

project(so_5)
...
find_package(timertt REQUIRED)
...

Если по факту её единстенное предназначение — собирать so, тогда как в SF'шном тарболле — просто класть рядом...

Короткий ответ такой: с гитхаба не нужно брать архивы исходников, нужно клонировать репозиторий, как написано в README.md на github.

Засчитывается за ответ :)

Если почему-то удобнее брать архив с гитхаба, то отпишите чуть подробнее, чтобы я смог понять, как это удобнее сделать.

Да просто 1) прямые ссылки (мой лог выше полностью воспроизводим), 2) не нагружает мой адблок своей классной рекламой. Ну т.е. не принципиально, взял с SF.

// Кстати о птичках — cmake'овская сборка не устанавливает набор заголовочных файлов.

Stil ★★★★★
()
Последнее исправление: Stil (всего исправлений: 1)
Ответ на: комментарий от Stil

Но ведь поинт тарболов именно в том, чтобы скачать архив и пользоваться.

А разве GH сейчас позволяет загружать специально подготовленные tar.gz или zip-файлы в качестве релизов? Ведь то, что GH показывает во вкладке tags — это просто ссылки на теги внутри репозитория. И ссылки для скачивания тега в виде zip или tar.gz — это просто выгрузка содержимого тега. И делается она, судя по всему, без учета особенностей git::submodules.

eao197 ★★★★★
() автор топика
Ответ на: комментарий от Stil

Т.е. чисто теоретически оно может использоваться отдельно — тогда можно прописать её как внешнюю зависимость.

По простому не получится. Репозиторий на гитхабе сделан с минимальными изменениями исходного svn репозитория, а там с помощью svn::externals часть репозитория timertt и двух других подпроектов тупо копируется внутрь дерева исходников SO. В принципе можно сделать размещение timertt в другом месте, даже делать поиск с помощью find_package(timertt REQUIRED), но придется переделывать исходную логику сборки прокта и вылавливать соответствующие ошибки. В результате возникнет 3 версии сборки: родная, cmake, работающий с svn, cmake, работающий с github.

Если по факту её единстенное предназначение — собирать so, тогда как в SF'шном тарболле — просто класть рядом...

Возможно, самый лучший вариант. Положить подпроекты в репозиторий SObjectizer и забыть, что они были подпроектами. Сейчас, когда репоизторий на github существует уже некоторое время и понятно, как он развивается, это вполне можно сделать. Насколько я понимаю, тарбол на github создается автоматически для каждого тега, в результате это единственный способ создать целостный тарбол (SObjectizer + 3 подпроекта).

// Кстати о птичках — cmake'овская сборка не устанавливает набор заголовочных файлов.

Изначально я это и не планировал. Хотел посмотреть, как пойдет работа с cmake, насколько это будет кому-то надо и сколько будет сложностей в поддержке. make install там только для того, чтобы можно было запускать тесты на винде (я серьезно).

Сейчас не очень понимаю, что делать с установкой заголовочных файлов. Они там вперемешку с .cpp исходниками, т.е. нет отдельной директории include, которую можно просто скопировать. Насколько такой подход нормальный для разработки я не знаю (я вообще не программист), а вот для копирований всех нужных заголовочных файлов в отдельную директорию точно не очень (делать кроссплатформенный скрипт, который копирует все .h файлы не очень хорошо, не факт, что их все нужно копировать, а перечислять все заголовки в отдельном списке тоже не супер, ибо поддержка всего этого упадет на разработчика). В общем тут думать нужно (и в первую очередь кому и для чего это нужно).

P.S. В результате, видимо, я сделаю SO и подпроекты в едином репозитории, если не возникнет каких-либо причин отказаться от этого. Для пользователей будет проще, для поддержки все то же самое.

prefetch
()
Ответ на: комментарий от prefetch

Изначально я это и не планировал. Хотел посмотреть, как пойдет работа с cmake, насколько это будет кому-то надо и сколько будет сложностей в поддержке. make install там только для того, чтобы можно было запускать тесты на винде (я серьезно).

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

:)

Сейчас не очень понимаю, что делать с установкой заголовочных файлов. Они там вперемешку с .cpp исходниками, т.е. нет отдельной директории include, которую можно просто скопировать. Насколько такой подход нормальный для разработки я не знаю (я вообще не программист), а вот для копирований всех нужных заголовочных файлов в отдельную директорию точно не очень (делать кроссплатформенный скрипт, который копирует все .h файлы не очень хорошо, не факт, что их все нужно копировать, а перечислять все заголовки в отдельном списке тоже не супер, ибо поддержка всего этого упадет на разработчика). В общем тут думать нужно (и в первую очередь кому и для чего это нужно).

Слушай, ну обычно это делается так:

...
set(MyLib_sources
    "src/src1.cpp")
set(MyLib_public_headers
    "include/hdr1.hpp")
set(MyLib_private_headers
    "src/hdr2.hpp")
...
set_target_properties(MyLib PROPERTIES
    PUBLIC_HEADER "${MyLib_public_headers}"
...
install(TARGETS MyLib
    ...
    PUBLIC_HEADER DESTINATION "${INSTALL_INCLUDE_DIR}/MyLib"

https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating...

Stil ★★★★★
()
Ответ на: комментарий от Stil

Слушай, ну обычно это делается так:

Это понятно, что создаются отдельные списки заголовочных файлов. Но тут есть одна нестыковка - их должен поддерживать разработчик (т.е. не я), а разработчик пользуется другой системой сборки, и cmake для него - то, чем пользуются все остальные, т.е. не в приоритете. В результате 3 списка исходников (на самом деле непонятно, зачем нужен список приватных заголовков) вместо одного пропорционально увеличат количество работы. Кроме того, если в ${MyLib_sources} пропустить файл - библиотека не соберется, если его пропустить в другом списке, то узнаешь об этом не скоро (если не писать специально для этого тесты).

Ну и главный вопрос - кому и для чего это нужно? Потребности в пакете (SDK) нет, потому и нет необходимости в скрипте копирования заголовков. Это на самом деле самое важное. Потому что хорошее решение задачи должно быть разработано с учетом особенностей самой задачи, а задачи нет. Еще когда я только задумал поддержку cmake для SObjectizer, я продумывал, что можно было бы сделать сборку пакетов, но тогда потребность в этом была непонятна, а потребность в cmake высказывалась в первых же комментариях тут при каждом анонсе очередной версии. Потому я для начала решил сделать поддержку cmake для сборки, а дельше посмотреть, что будет нужно еще. С тех пор я и не пытался реализовать сборку пакетов.

prefetch
()
Ответ на: комментарий от prefetch

Ну и главный вопрос - кому и для чего это нужно?

Скорее даже так: нужно ли это кому-то?

Если будут люди, которые будут использовать SO-5 в виде набора заголовочных файлов и скомпилированных библиотек, то сделать объявление набора публичных hpp-файлов в CMakeLists.txt не проблема. Это не обязательно даже вручную делать, можно какой-нибудь скрипт налабать.

eao197 ★★★★★
() автор топика

Вышла версия 5.5.9

SObjectizer обновился до версии 5.5.9. Вкратце изменения таковы:

  • возможность использовать произвольные типы в качестве типов сообщение (наследование от message_t больше не обязательно, но тип должен быть MoveConstructible);
  • класс wrapped_env_t, позволяющий работать с SObjectizer Environment в более привычном для ООП стиле;
  • возможность трассировки механизма доставки сообщения (для упрощения отладки SObjectizer-приложений и поиска ошибок, связанных с подписками и отсылкой сообщений не тем получателям);
  • новые функции request_value и request_future для упрощения синхронного взаимодействия агентов;
  • несколько новых вариантов функции send, позволяющие использовать send вместо send_to_agent (что удобно при обобщенном программировании);
  • исправлено несколько ошибок, добавлена пара новых примеров.

Чуть подробнее об изменениях рассказывается в этой презентации или в этом посте. Полный список изменений можно найти в Wiki.

Так же сделаны две новые презентации, которые коротко рассказывают о таких возможностях SO-5.5, как синхронное взаимодействие агентов и лимиты для сообщений.

Версию 5.5.9 можно взять либо из секции Files на SF, либо из Svn-репозитория, либо из зеркала на GitHub (на GitHub-е теперь git submodules не используется, так что самую последнюю версию можно просто скачать с GitHub-а в виде архива и в ней сразу будут все необходимые подпроекты).

eao197 ★★★★★
() автор топика

В обсуждениях SO-5 часто упоминалось, что у нас не удобный/понятный API. Есть желание сделать его удобнее и понятнее. Например, вот такой шаг был бы шагом в верном направлении?

eao197 ★★★★★
() автор топика

Механизм mchain

Вот какая штука готовиться к релизу в версии 5.5.13. Уже полностью работает, но окончательно не зафиксирована. Поэтому еще есть возможность что-то переделать, если вдруг обнаружатся какие-то фатальные недостатки.

eao197 ★★★★★
() автор топика
Ответ на: Механизм mchain от eao197

Когда-нибудь я обязательно придумаю зачем он мне нужен и осилю дочитать доку. Пока чота неосиливаю примеры. Как-то намешано все и непонятно.

Кстати автор, а ты пробовал взять какой-нить опенсорс проект и внедрить в него, ну чтоб понятно было «вот так было криво-запутано» -> «вот так стало круто-понятно-расширяемо»? ну или не ты конкретно, а кто-нибудь из причастных.

anonymous
()
Ответ на: комментарий от anonymous

Как-то намешано все и непонятно.

Ткните пальцем во что-то непонятное. А то непонятно, что вам не понятно.

а ты пробовал взять какой-нить опенсорс проект и внедрить в него

Нет.

eao197 ★★★★★
() автор топика
Ответ на: комментарий от eao197

Ткните пальцем во что-то непонятное

окей. Открываем basic http://sourceforge.net/p/sobjectizer/wiki/so-5.5 Basics/

Читаем про среду (env), читаем про launch, все как бы понятно ... а потом

/*The so_5::launch() function has two forms. 
The first one receives just one argument -- 
it is a function object (or lambda) with initialization actions:
*/
so_5::api::launch( []( so_5::rt::environment_t & env ) {
      env.introduce_coop( [&]( so_5::rt::agent_coop_t & coop ) {
        coop.define_agent().on_start( [&] {
            std::cout << "Hello, world!" << std::endl;
            env.stop();
          } );
      } );
   } );

мля .. и тут ты понимаешь, что читать дальше уже не охота.

Далее еще больше кода, который непонятно что и зачем. Я понимаю, что автору это отлично понятно.ладно, думаю, дочитаю. Дочитал, понял про слоты, боксы. Но кода СИЛЬНО много для Basic КМК. Далее я открыл пример пингера и понял, что не хочу я больше ни читать. ни пробовать...

Как надо писать? Критикуя - предлагай! да легко вот пример https://thrift.apache.org/ 1 страница с примером Далее идем в каталог с примерами https://git-wip-us.apache.org/repos/asf/thrift/?p=thrift.git;a=tree;f=tutoria...

открываем любой клиент или сервер и видим ОТЛИЧНЫЕ ПРОСТЫЕ примеры. смысл в том, чтоб не ВЫГЛЯДЕТЬ как лапша из кода. https://git-wip-us.apache.org/repos/asf/thrift/?p=thrift.git;a=blob_plain;f=t... Все подряд. даже не читая комментарии можно понять за что отвечает каждая строка. То же самое с серверной частью. Но там еще даже лучше. Там в 1 ПРОСТОМ исходнике показано как сделать если нужно peer2peer или если не нужно. Все сделано просто, черт возьми! Хочется всять и использовать этот thrift, потому что для того, чтоб понять его основы мне хватило 1 минуты. в SO я пялился пол дня и из-за обилия лесенок кода и лямбд у меня потекли глаза. :(

Ну вот как-то так.

anonymous
()
Ответ на: комментарий от anonymous

Даже не знаю, что сказать. Раздел Basic реально описывает только самые базовые вещи, да и то, по верхам.

С++ники сейчас очень разные. Кому-то нравится код с лямбдами (вот здесь, например, сравнение одного и того же актора/агента, реализованного с помощью CAF и с помощью SO-5, а здесь сравнение с Just::Thread Pro Actors Edition). Кому-то старый добрый ОО-стиль в духе Qt или даже MFC.

Тот же самый hello-world, который сделал полностью на лямбдах, можно представить полностью в олд-скульном стиле:

#include <iostream>

#include <so_5/all.hpp>

using namespace std;
using namespace so_5::rt;

class a_hello_t : public agent_t
{
	public:
		a_hello_t( context_t ctx ) : agent_t{ ctx }
		{}

		virtual void so_evt_start() override
		{
			cout << "Hello, world! This is SObjectizer v.5." << endl;

			so_environment().stop();
		}

		virtual void so_evt_finish() override
		{
			cout << "Bye! This was SObjectizer v.5." << endl;
		}
};

int
main()
{
	try
	{
		so_5::wrapped_env_t sobj;

		auto coop = sobj.environment().create_coop( "hello" );
		coop->make_agent< a_hello_t >();
		sobj.environment().register_coop( move(coop) );

		sobj.join();
	}
	catch( const exception & ex )
	{
		cerr << "Error: " << ex.what() << endl;
		return 1;
	}

	return 0;
}
Просто лично мне кажется, что вместо:
so_5::wrapped_env_t sobj;
...
sobj.join();
удобнее написать:
so_5::launch( []( environment_t & env ) {
...
} );
А вместо:
auto coop = sobj.environment().create_coop( "hello" );
coop->make_agent< a_hello_t >();
sobj.environment().register_coop( move(coop) );
удобнее писать:
env.introduce_coop( []( coop_t & coop ) {
  coop.make_agent< a_hello_t >();
} );
ну и т.д.

Видимо, в Wiki нужно будет сделать раздел Basics for Old-Schoolers :)

eao197 ★★★★★
() автор топика
Ответ на: комментарий от eao197

Немного соврал, можно даже еще более олд-скульно:

auto coop = sobj.environment().create_coop( "hello" );
coop->add_agent( new a_hello_t{sobj.environment()} );
sobj.environment().register_coop( move(coop) );

eao197 ★★★★★
() автор топика
Ответ на: комментарий от eao197

Тот же самый hello-world, который сделал полностью на лямбдах, можно представить полностью в олд-скульном стиле:

IMHO самое читабельное для вводной документации. Потом, где-то в advanced, можно указать другие варианты.

З.Ы. сам сабжа в глаза не видел, потому взгляд со стороны.

Pavval ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.