LINUX.ORG.RU

SObjectizer-5.6.0: новая мажорная версия акторного фреймворка для C++

 , , , ,


0

2

SObjectizer — это относительно небольшой фреймворк для упрощения разработки сложных многопоточных приложений на C++. SObjectizer позволяет разработчику строить свои программы на базе асинхронного обмена сообщениями с использованием таких подходов, как Actor Model, Publish-Subscribe и CSP. Это открытый проект под лицензией BSD-3-CLAUSE. Краткое впечатление о SObjectizer можно составить на основании вот этой презентации.

Версия 5.6.0 является первым мажорным релизом новой ветки SObjectizer-5.6. Что означает также завершение развития ветки SObjectizer-5.5, которая развивалась более четырех лет.

Поскольку версия 5.6.0 открывает новую главу развития SObjectizer, то нововведений совсем нет в сравнении с тем, что было изменено и/или удалено из SObjectizer. В частности:

  • используется C++17 (ранее обходились подмножеством C++11);
  • проект переехал и живет теперь на BitBucket с официальным, а не экспериментальным, зеркалом на GitHub;
  • у коопераций агентов нет больше строковых имен;
  • из SObjectizer удалена поддержка синхронного взаимодействия между агентами (его аналог реализован в сопутствующем проекте so5extra);
  • удалена поддержка агентов ad-hoc;
  • для отсылки сообщений теперь используются только свободные функции send, send_delayed, send_periodic (старые методы deliver_message, schedule_timer, single_timer из публичного API изъяты);
  • функции send_delayed и send_periodic теперь имеют единый формат вне зависимости от типа получателя сообщения (будь то mbox, mchain или ссылка на агента);
  • добавлен класс message_holder_t для упрощения работы с преаллоцированными сообщениями;
  • удалено множество вещей, которые были помечены как deprecated еще в ветке 5.5;
  • ну и еще всякое разное.

Более развернутый список изменений можно найти тут. Там же, в Wiki проекта, можно найти документацию по версии 5.6.

Архивы с новой версией SObjectizer можно взять на BitBucket или на SourceForge.

PS. Специально для скептиков, которые считают, что SObjectizer никому не нужен и никем не используется. Это не так.

>>> Подробности

★★★★★

Проверено: Shaman007 ()

PS. Специально для скептиков, которые считают, что SObjectizer никому не нужен и никем не используется.

Тихо, а то сейчас придут РЕАЛЬНЫЕ программисты и будут рассказывать про Spring'и и Hibernat'ы и что на C++ пишут только ПТУшники.

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

Да как бы давно хотелось, тем более что это первый настолько знаковый релиз за последние 4.5 года. Скромность уговаривала отказаться от таких «понтов», но если на главную пускают недопиленные студенческие курсовые... То чего стесняться-то.

Тем более, что по большому счету публично известных, живых и развивающихся, открытых кроссплатформенных фреймворков такого рода в мире C++ всего несколько штук.

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

Не все еще могут себе позволить C++17, к сожалению. Была ли в этом действительно сильная необходимость?

В свое время и C++11 не все могли себе позволить.

Но вообще все просто: SObjectizer – это открытый и бесплатный проект, который нам денег не приносит. Несколько лет назад у нас был интерес в том, чтобы обходиться только подможеством C++, и какое-то время мы считали это своим конкурентным преимуществом.

Но сейчас у нас такого интереса нет. Ну и возникает логичный вопрос: а зачем нам тратить свое время и свои ресурсы на трах со старыми компиляторами? Тем более, что интерес к SObjectizer-у растет медленно. И когда этот интерес вырастет настолько, что SObjectizer будет применяться широко, то C++17 уже не будет передним краем.

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

Как я понимаю, новость появилась в первую очередь из-за публикации на главной странице всякого непотребства про FastCGI на C++17, так? :D

Как я понимаю, новость появилась в первую очередь из зависти, так? :D

// fixed

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

Ну наконец-то!!!

Актуальное зеркало на GitHub-е было и раньше (года четыре как). Так что это изменение более существенно для нас самих, чем для пользователей.

eao197 ★★★★★ ()

ранее обходились подмножеством
переехал
нет больше
удалена поддержка
удалена поддержка
изъяты

изъят ли данный проект из Gnome 3.0 ?

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

когда этот интерес вырастет настолько, что SObjectizer будет применяться широко, то C++17 уже не будет передним краем

я тоже так периодически думаю и меня останавливает только одно: некоторые популярные платформы (популярнее онтопика) до сегодняшнего дня не полностью поддерживают с++11. потому что с++ - это не только конпелятор, но ещё и рантайм.

я думаю вы с такими проблемами просто ещё не сталкивались, надеюсь всё сложится как вам хочется. хотя хипсторы со смузи уже вовсю топят за ecs и против акторов, но хипсторы со смузи тоже лабают своё барахло на с++3z поэтому в общем-то пофиг, хоть на тайпскрипте, в этом плане без разницы.

удачи.

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

некоторые популярные платформы (популярнее онтопика)

А это какие? Действительно интересно (у нас если и спрашивают, то разве что про Android и iOS). В прошлом упоминалась еще и QNX, но это и все.

удачи.

Спасибо!

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

Да. А в чем проблема?

Разработка приложений на основе асинхронных сообщений усложняет разработку на порядок, а то и на несколько порядков. А так проблем нет.

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

Разработка приложений на основе асинхронных сообщений усложняет разработку на порядок, а то и на несколько порядков.

Как минимум, пользователи Erlang/Elixir и Akka, а так же разработчики на Go, с вами сильно не согласятся.

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

Как минимум, пользователи Erlang/Elixir и Akka, а так же разработчики на Go, с вами сильно не согласятся.

Честно говоря, я не в курсе как там у них в Erlang и Akka, но какое это имеет отношение к разработке в С++? Разработка на основе событий имеет место быть и бывает оправдана по разным причинам. Но имхо - упрощение процесса разработки не одна из этих причин ни разу.

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

Честно говоря, я не в курсе как там у них в Erlang и Akka

Ясно-понятно.

но какое это имеет отношение к разработке в С++?

Самое прямое. Собственно, я об этом уже подробно рассказывал, нет смысла повторяться.

Но имхо - упрощение процесса разработки не одна из этих причин ни разу.

С таким имхо разве поспоришь?

А вот в новости ссылка на опыт использования была, там человек пишет, что упрощает.

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

Разработка приложений на основе асинхронных сообщений усложняет разработку на порядок, а то и на несколько порядков. А так проблем нет.

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

И, кстати, про обмен асинхронными сообщениями - так Qt работает со своими сигналами и слотами. Все рады. Так GoLang работает со своими Go-рутинами и каналами. Народ пищит от восторга. Да и вообще, сделать синхронный вызов метода объекта, который работает в другом потоке - потерять преимущества многопоточности. Так что в многопоточке обязательно будет в каком-то виде асинхронщина и обмен сообщениями.

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

А вот в новости ссылка на опыт использования была, там человек пишет, что упрощает.

Целый один пишет? Ну тогда это все меняет. Несомненно можно найти (специально подобранную) задачу, где с асинхронным программированием все становится легко и просто. Однако в реальной жизни не все так просто и гладко, к сожалению. Достаточно сравнить размер и сложность кода при такой простой задаче, как запрос и получение данных с сервера базы данных. С предварительным логином и восстановлением соединения если нужно. Обычный синхронный код будет тривиальным, асинхронный будет довольно сложен для понимания - отслеживание состояний и прочая.

В финансах очень распространен подход разработки с помощью различных pub/sub систем - тоже самое асинхронное программирование. Начальный этап разработки - да упрощает. Но что случается потом, об этом стараются не упоминать...

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

Асинхронный код, однозначно сложнее синхронного. Но тут речь о другом. Если тебе нужна многопоточка, то без асинхронщины и сообщений не обойтись. И тут быстро становится понятно, что мьютексы и условные переменные подходят для решения только простых задач. Для более сложных нужны другие инструменты. SO один из таких, т.е. с ним проще разрабатывать многопоточный код, чем без него. Разумеется, он подходит не для любой задачи.

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

Речь про многопоточные приложения, ты почему-то этот момент упорно пропускаешь.

Нет не пропускаю, многопоточные приложения да сложнее, но все равно проще, чем асинхронные.

И, кстати, про обмен асинхронными сообщениями - так Qt работает со своими сигналами и слотами.

Работает конечно, потому что хорошо ложиться на предметную область - так работает GUI. Но вот наваять сложную систему на сигналах и слотах, где вся логика так имплементирована - легче убиться.

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

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

Ок. Расскажи, какие ты знаешь способы реализации многопоточных приложений. Более простые, чем актеры/агенты, работающие на разных потоках и общающиеся через очереди сообщений или Go-рутины с каналами.

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

олее простые, чем актеры/агенты, работающие на разных потоках и общающиеся через очереди сообщений или Go-рутины с каналами.

Я не знаю, что такое Go-рутины с каналами, но проще, чем актеры/агенты, работающие на разных потоках и общающиеся через очереди сообщений это пул потоков, каждый поток из которого работает синхронно, если это необходимо.

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

Многопоточка это в первую очередь разделяемые данные (иначе нет разницы с однопоточным кодом). И доступ к этим данным нужно как-то синхронизировать. Так что пулы - это только часть истории, самая простая и очевидная.

Как защищать доступ к общим данным?

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

Целый один пишет?

Целый один потрудился взять и описать свой опыт.

Однако в реальной жизни не все так просто и гладко, к сожалению.

Не все. Так никто и не обещал, что SObjectizer облегчает написание любых многопоточных приложений. Некоторых упрощает и сильно. Ссылку на статью, где описаны критерии для выбора, я уже давал выше. Если вам лень читать, то почему мне не должно быть лень вам что-то объяснять?

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

А теперь давайте представим, что у вас таких параллельных запросов 500K.

А теперь попробуйте представить, как эти 500K запросов должен обрабатывать этот самый сервер БД. Ему ведь нужно запросы принимать, парсить, строить планы, работать с кэшем и диском и т.д. и т.п.

Думаете, все это будет легко сделать на обычных нитях, мутексах и кондишенах? И что очереди сообщений здесь никак не помогут?

Ну ОК, не буду вас разубеждать.

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

А это какие?

чтобы треды работали под оффтопиком, в мингв поддерживают библиотечку winpthreads. потоки под осх - это боль в попе, я почему-то уверен, что сборочка osxcross в рач-линуксе не совсем умеет в потоки, ну мне так кажется, я не проверял.

ну или новый шланг например не компилирует эпловскую стандартную библиотеку потому что в ней ошибки на которые старый шланг не обращал внимания потому что ошибки были в шланге.

но это так, мелочи жизни. я думаю, что с появлением нетворкинга и файловых систем в с++ количество проблем с рантаймом будет возрастать. но в использовании новья конечно же есть смысл, glm например с с++2а умеет компилироваться, только не эксклюзивно, он поддерживает с++98/11/14/17/2а.

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

чтобы треды работали под оффтопиком, в мингв поддерживают библиотечку winpthreads.

Так std::thread вполне себе реализован под Windows в VC++, со времен эдак MSVS2012 (если не раньше). Бывали там особенности, но, во-первых, решаемые. И, во-вторых, MS их исправляла в последующих версиях.

Под macOS у нас SO собирается clang-ом из XCode без проблем. Вроде жалоб еще не было.

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

А теперь попробуйте представить, как эти 500K запросов должен обрабатывать этот самый сервер БД.

Ога, 500000 параллельных запросов на сервере БД. Лол. Много знаешь таких СУБД? Научи коннектиться к таким серверам из параллельной вселенной, фантазер.

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

Много знаешь таких СУБД?

Нет. А вам нужно обязательно много?

Насколько я слышал, 500K параллельных запросов для DynamoDB – это обыденность.

Ну и под «сервер БД» не обязательно понимать один-единственный физический сервер.

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

пул потоков, каждый поток из которого работает синхронно, если это необходимо.

Конечно же это легче. Асинхронщина, особенно явная - это всегда лапша, которую запаришься отлаживать, если чо.

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

Асинхронщина, особенно явная - это всегда лапша, которую запаришься отлаживать, если чо.

Не совсем. Асинхронщина в виде корутин C++20 стала совсем не лапшой (а для пользователя асинхронного кода совсем похожа не синхронный). Это по сравнению с другими решениями: разбиению конечного автомата на части как в boost::ASIO, фьюче-промисами, но только не из C++11, а из других языков, где промис - это список действий, а фьючи может вообще не быть, ручным написанием конечного автомата методом Даффа или как-то еще. В C++20 корутины реализованы в виде конечного автомата методом Даффа, только этот автомат генерируется компилятором из кода, похожего на синхронный. Хотя некоторые особенности поведения этого автомата нужно писать вручную и в языке без GC это заставляет хорошо продумать многие мелочи (как минимум объект-корутина должен не умереть, пока его данные кому-то нужны и удалиться, когда надо). Но если ты не автор асинхронной библиотеки, а ее пользователь, то код не сильно отличается от синхронного (по виду, но, определенно, сложнее в написании и отладке).

anonymous ()

Я не нашел, а где тут гипервизоры, которые управляют жизненным циклом акторов? Например перезапускают в случае их падения? И гипервизоры гипервизоров для построения дерева гипервизоров со сложными связями?

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

Насколько я слышал, 500K параллельных запросов для DynamoDB – это обыденность.

Ну вот теперь то пользователи ЛОРа знают какие инструменты использовать для следующего проекта: C++, SObjectizer и Amazom DynamoDB чтобы обработать 500000 параллельных запросов в секунду.

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

Думаете, все это будет легко сделать на обычных нитях, мутексах и кондишенах? И что очереди сообщений здесь никак не помогут?

Написать сервер, который сможет обрабатывать 500K запросов непросто полюбому. Прикол в том, что я могу реализовать очереди сообщений на обычных мьютексах и кондишенах, и даже прицепить «lock free». Но использовать очереди сообщений и сделать код полностью асинхронным - это две большие разницы. К сожалению эта модель плохо уживается с обычным, блокируемым кодом.

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

А их тут нет. Это C++, не Erlang. Тут если херня случается, то падает все приложение, а не один конкретный агент.

Но, если хочется иметь что-то похожее на Erlang, то можно сделать руками:

  • во-первых, агенты регистрируются в кооперациях. Если какой-то агент «падает» (выпускает наружу исключение и реакция на него установлена в «deregister-coop»), то автоматически будут изъяты и все остальные агенты из кооперации. Что-то вроде one-for-all, если не ошибаюсь;
  • во-вторых, можно использовать нотификаторы для коопераций чтобы рестаровать кооперации, которые завершили свою работу из-за ошибки (пример можно увидеть здесь).

Но, повторюсь, это C++, здесь от супервизоров внутри самого процесса толку мало. Если уж так хочется максимального приближения к Erlang-у, то вам сюда: CAF.

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

Прикол в том, что я могу реализовать очереди сообщений на обычных мьютексах и кондишенах

Прикол в том, что вы можете взять готовую реализацию. Тот же SObjectizer, например.

Но использовать очереди сообщений и сделать код полностью асинхронным - это две большие разницы.

Если вас SObjectizer заставляет делать код полностью асинхронным, то SObjectizer вам не подойдет. В этом можете не сомневаться.

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

Если вас SObjectizer заставляет делать код полностью асинхронным, то SObjectizer вам не подойдет. В этом можете не сомневаться.

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

Прикол в том, что вы можете взять готовую реализацию. Тот же SObjectizer, например.

Могу, но использовать очередь сообщений совсем не тоже самое, что использовать модель Акторов и тянуть весь SObjectizer, только чтобы выдернуть оттуда очередь сообщений? А смысл? Да и возможно ли это, использовать SObjectizer без перехода на полностью асинхронную модель?

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

Не меня, а всех.

И что вам позволяет говорить за всех?

Сама модель один объект - одна нить

Откуда взялась эта модель?

Могу, но использовать очередь сообщений совсем не тоже самое, что использовать модель Акторов и тянуть весь SObjectizer

Я понимаю, что вы ничего не хотите знать про SObjectizer. Но, пилять, текст новости, в обсуждение которой вы решили вступить, вы прочитать можете? Упоминание Pub/Sub и CSP там в состоянии рассмотреть?

Может просто чукча не читатель?

А смысл?

Экономия сил и времени, т.к. SObjectizer – это не только очереди.

Да и возможно ли это, использовать SObjectizer без перехода на полностью асинхронную модель?

Можно. Здесь есть примеры. На асинхронных сообщениях только часть логики.

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

Ага, потому что под macOS его никто не использует...

Я бы даже согласился, если бы не приходилось решать время от времени проблемы со сборкой под macOS.

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

Откуда взялась эта модель?

Это ваша статья, которую тут рекомендовали? https://habr.com/ru/post/322250/ Это цитата из вашей статьи:

Вместо того, чтобы иметь N потоков, которые конкурируют друг с другом за ресурсы, можно сделать M потоков, каждый из которых будет владеть собственными данными. Ни один из потоков не имеет доступа к данным других потоков.

А вот в чем разница, вы говорите про данные, а я говорю про объект. Но это разве не одно и тоже?

Может просто чукча не читатель?

Может чукча прочитает свою статью?

Если же потоку X нужно что-то от другого потока Y, то поток X помещает сообщение во входящую очередь потока Y.

Это что не подразумевает, что поток Y тоже становится асинхронным? И так далее по списку. Чем это отличается от того, что я сказал ранее?

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

Это ваша статья, которую тут рекомендовали?

Моя.

А вот в чем разница, вы говорите про данные, а я говорю про объект. Но это разве не одно и тоже?

Один поток, вообще-то говоря, может обслуживать несколько объектов. Это актуально и для SObjctizer-а, и для реализаций stackful короутин на базе файберов, и для реализаций гороутин в Go.

Так что взаимоотношение один поток = один объект — это актуально для отдельных реализаций модели акторов (вроде Erlang-а), но не для всех.

Это что не подразумевает, что поток Y тоже становится асинхронным?

С чего бы это? Между потоками X и Y взаимодействие происходит посредством асинхронного обмена сообщениями. Т.е. когда X отправляет сообщение Y, то Y не обязан сидеть и ждать это сообщение.

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

Чем это отличается от того, что я сказал ранее?

Простите, что именно из того, что вы сказали ранее? Тут уже много вы наговорили.

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

Один поток, вообще-то говоря, может обслуживать несколько объектов.

Это вопрос терминологии. Принципиально тут то, что поток имеет экслюзивный набор данных. Я весь этот набор называю объектом, вы нет, суть от этого не меняется.

С чего бы это? Между потоками X и Y взаимодействие происходит посредством асинхронного обмена сообщениями. Т.е. когда X отправляет сообщение Y, то Y не обязан сидеть и ждать это сообщение.

С того, что если Y взаимодействует с X посредством «асинхронного обмена сообщениями» это налагает требования на Y

1 - Y должен уметь обрабатывать асинхронные сообщения. 2 - Y не должен блокироваться при обработке сообщений.

Из 2 следует, что Y должен общаться с другими посредством «асинхронного обмена сообщениями». А из 1 и 2 следует, что Y должен быть таким же как X - асинхронно обрабатывать. И так далее по списку.

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

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

rGlory ()