LINUX.ORG.RU

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

 , , ,


4

1

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

Последние несколько лет SObjectizer развивается на SourceForge как OpenSource проект под BSD-лицензией. Подробнее об истории, текущем состоянии и направлении движения SObjectizer можно прочитать здесь.

Версия 5.5.0 является результатом очередного, очень значимого этапа развития проекта.

Главное отличие v.5.5.0 от предыдущих версий — это отсутствие зависимости от ACE Framework. Т.е. теперь ACE в коде ядра SObjectizer не используется вообще, для SObjectizer достаточно наличия стандартной библиотеки C++11. Это означает, что SObjectizer уменьшился в размере, нужно меньше времени на сборку SObjectizer-проектов, упрощается поддержка различных компиляторов и платформ. В частности, эта версия SObjectizer тестировалась посредством MSVS2013 (Windows), GCC 4.8/4.9 (Windows, Linux), Clang 3.5.0 (Linux).

Из более мелких изменений можно отметить прямую поддержку std::chrono при работе с отложенными/периодическими сообщениями, а так же небольшое изменение названий некоторых классов/функций (с сохранением старых имен для обеспечения совместимости). Более подробная информация о нововведениях в v.5.5.0 доступна в соответствующем разделе Wiki проекта. Так же увеличилось количество страниц с описаниями базовых вещей SObjectizer.

Версия 5.5.0 может быть загружена из раздела Files или получена из Subversion-репозитория.

Примечание. Этот релиз содержит только ядро SObjectizer (т.е. проект so_5). Никакие другие подпроекты (вроде so_log или so_sysconf) в релиз не включены. Возможно, сборка SObjectizer Assembly со всеми подпроектами будет сформирована и опубликована позже (если она действительно кому-то потребуется).

PS. Анонс делается просто для того, чтобы уведомить, что такой проект есть, живет, развивается. Доступен под BSD-лицензий, т.е. даром, в том числе и для коммерческих проектов. Это не просьба сделать code review. И не попытка кому-то что-то «продать».

PPS. Специально для желающих постебаться над синтаксисом и посравнивать программирование на C++ с Perl-ом. Вот классический пример Hello, World. В традиционном, ООП-шном варианте, с созданием класса агента и переопределением виртуальных методов (хотя есть и более модерновый вариант, с использованием С++ных лямбда-функций):

#include <iostream>

// Main SObjectizer header files.
#include <so_5/all.hpp>

// Definition of an agent for SObjectizer.
class a_hello_t : public so_5::rt::agent_t
{
	public:
		a_hello_t( so_5::rt::environment_t & env )
			: so_5::rt::agent_t( env )
		{}

		// A reaction to start of work in SObjectizer.
		virtual void
		so_evt_start() override
		{
			std::cout << "Hello, world! This is SObjectizer v.5."
				<< std::endl;

			// Shutting down SObjectizer.
			so_environment().stop();
		}

		// A reaction to finish of work in SObjectizer.
		virtual void
		so_evt_finish() override
		{
			std::cout << "Bye! This was SObjectizer v.5."
				<< std::endl;
		}
};

int
main( int, char ** )
{
	try
	{
		// Starting SObjectizer.
		so_5::launch(
			// A function for SO Environment initialization.
			[]( so_5::rt::environment_t & env )
			{
				// Creating and registering single agent as a cooperation.
				env.register_agent_as_coop( "coop", new a_hello_t( env ) );
			} );
	}
	catch( const std::exception & ex )
	{
		std::cerr << "Error: " << ex.what() << std::endl;
		return 1;
	}

	return 0;
}

PPPS. Специально для желающих узнать, чем SObjectizer лучше libcppa/CAF. В двух словах — это две совершенно разные разработки, ставящие перед собой разные цели и достигающие их разными способами. Подробнее здесь и здесь.

★★★★★

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

вероятно потому, что не знаком с этой парадигмой.

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

рассмотрим задачу, которая в хай-лоаде встречается на каждом шагу: есть key-value таблица, с которой работают много «агентов» (обычно по одному на пользовательское подключение). проблема в том, что её иногда обновляют. таким образом, им надо между собой договориться о чём-то похожем на rw-lock-и (в традиционных шаблонах нагрузки реализация с writer starvation обычно считается предпочтительной). так вот, претендующая на «помощь» библиотека должна содержать соответствующий примитив, а не заставлять пользователя велосипедить его каждый раз вручную.

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

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

У меня есть подозрение, что речь идет совсем не о том. Но давайте пока не углубляться. Вы упомянули про поддержку стандартных протоколов. О чем именно идет речь: AMQP, SNMP, ...?

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

Теперь понятно, о чем именно речь. Можно вернуться чуть назад.

событийно-ориентированная. нужна развитая система событий (см libevent или winapi).
агентно-ориентированная. нужны реализации как минимум стандартных протоколов взаимодействия.

Если коротко, то задачей SO5 было именно сделать «только переключение контекстов». Предыдущая версия, SO4, кроме переключения контекстов давала возможность пользователю писать распределенные приложения, для чего предоставляла прозрачную передачу некоторых сообщений между процессами (вроде того, что сейчас есть в libcppa). Но со временем мы решили разделить функциональность по уровням. Самый нижний уровень, т.е. ядро, т.е. библиотека SO5, реализует привязку объекта-агента к контексту, позволяет объекту-агенту определить состояния и события в каждом из состояний, обеспечивает доставку сообщений до агентов и запускает агента для обработки сообщения.

Над ядром разрабатываются дополнительные слои. Например, слой для собирания приложения из dll/so-шек с агентами, как из кубиков. Или слой для обмена сообщениями между несколькими приложениями.

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

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

Например, самый простой случай, с которого, собственно, и стартовали работы над SO4. GUI-приложение, которое позволяет пользователю работать со SmartCard-ами, подключенными к компьютеру через ридеры. Библиотека для работы с ридерами синхронная, операции довольно длительные, выполнять их на главной нити приложения не есть хорошо, пользователь должен иметь возможность двигаться по приложению, пока идет работа с ридером. Соответственно, работа с ридерами оформляется в виде активных агентов, которые живут на своей нити, на которой и общаются с ридерами. А с внешним миром (т.е. с GUI) общаются посредством сообщений.

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

Так, если приложение получает запросы по HTTP в виде XML, то не SO5 будет отвечать за прием TCP-подключений, вычитывание и парсинг HTTP POST-а. А вот когда уже есть голый XML и этим нужно что-то сделать (например, извлечь данные; проверить криптографическую подпись, расшифровать; проверить, новый ли это запрос; проверить возможность обслуживания этого запроса; зафиксировать его в БД; определить конечную систему для обработки запроса; передать запрос туда; дождаться ответа или напомнить о запросе еще раз или переодически запрашивать статус/результат; зафиксировать результат в БД; подготовить ответ (с шифрованием, подписью); отдать результирующий XML назад транспортному слою)... Вот тогда логику можно писать на SO5. Причем в зависимости от специфики задачи либо под каждый запрос можно создавать объект-агент (Erlang style), либо создавать агентов под каждую стадию обработки (SEDA style).

Что касается агентных систем масштаба FIPA, то это вообще уже какой-то очень высокий уровень. На который мы никогда и не претендовали (подробнее здесь). В принципе, на SO5 можно сделать приложение-агент для FIPA, то в такой реализации SO5 будет всего лишь одним из строительных блоков, над которым нужно будет еще что-го выстраивать.

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

за 8-й пачкой стоит идти? :)

Ктож его знает? :)

Но восьмая страница обсуждения и так уже идет :))

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

Кстати, есть ли/планируются ли встроенные средства для горизонтального масштабирования SO?

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

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

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

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

Судя по описанию вашей задачи, вам нужно смотреть в сторону протоколов из области M2M, в частности, есть такой стандарт, как DDS, в котором основной вид транспорта UDP и есть поддержка автоматического поиска объектов взаимодействия. Есть несколько реализаций, в том числе и OpenSource.

Я не спец в этой теме, просто интересовался, но может быть вам будет интересна подборка информации у меня по теме IoT/M2M.

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

Не, эти все протоколы рассчитаны на более-менее стационарную структуру сети. В MANET мы такой блажи лишены, если библиотека не заточена под то что узлы постоянно появляются/исчезают, то попытка ее затачивания под собственные нужды приводит к аду в коде. Про DDS, почитаю, спасибо. Сейчас используем самописную (Erlang) систему обмена сообщениями, но она достаточна тяжеловесна и использовать ее для синхронизации двух устройств со стабильной связью просто оверкилл.

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

Тема интересная, но вряд ли для обсуждения на публичном форуме. Если будет желание пообщаться, со мной можно на gmail-е связаться, имя ящика такое же, как мой ник здесь.

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

ну не такие тонны кода :)

Неужели мало? ;)

там показывались примеры решений реальных задач

Дык с Оберонщиками все проще. У них даже присваивание нового значения переменной — это реальная задача. Ведь это обязательно должно быть записано как a:=b, но ни в коем случае не a=b, поскольку a=b — это сравнение на равенство, а a==b — это неучи-программисты придумал, потому что математику неасилили :)

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

Поэтому и приходится топтаться где-то на микроуровне.

Вот, скажем, отсылка и получения сообщения в SO — это же, в принципе, тоже прикладная задача. Самая распространенная, с которой программисту приходится иметь дело в SO-приложении. Вообще, SO можно рассматривать как библиотеку, которая всего лишь дает программисту реализацию очередей сообщений. А очереди сообщений есть много где. В ACE, например, есть Message_Block и Message_Queue, более того, там даже есть базовые классы обработчиков, которые позволяют строить цепочки обработки сообщений (вот вроде бы код, иллюстрирующий использование этих механизмов).

В Qt уже есть средства для передачи сообщений QObject-ам, работающим на других нитях. Я уже давал здесь ссылку на реализацию хамелеонов на SO. К ней мой давний знакомый сделал вариант на Qt, с использованием механизмов signal-slot. Вот исходники. Можно посмотреть, во что выливается оформление и обработка события средствами Qt:

// Определение события.
class ChangeColorEvent : public QEvent
{
public:
  static const int changeColorEventType;
public:
  ChangeColorEvent( Color c )
    : QEvent( static_cast< QEvent::Type >( changeColorEventType ) )
  ...
};
const int ChangeColorEvent::changeColorEventType = QEvent::registerEventType();

// Обработка события:
bool Chameleon::event( QEvent * e )
{
  if( e->type() == ChangeColorEvent::changeColorEventType )
  {
    ChangeColorEvent * event = static_cast< ChangeColorEvent* > ( e );
    changeColor( event->color() );
    return true;
  }
  else
    return QObject::event( e );
} 
Т.е. старый, добрый диспатчинг сообщений вручную, как в приснопамятные времена голых WndProc :)

Тогда как в SO5:

struct msg_meeting_result : public so_5::rt::message_t
{
	color_t m_color;

	msg_meeting_result( color_t color )
		:	m_color( color )
		{}
};
...
void
a_chameleon_t::evt_meeting_result(
	const msg_meeting_result & evt )
{
...
}

И это мы еще рассматриваем сценарий обмена сообщениями 1-to-1, если нужно сделать 1-to-N, то в ACE или Qt придется самому писать какой-то класс MessageBoard. И доставка сообщений через который будет отличаться от обычной 1-to-1 доставки. Тогда как в SO multi-consumer mbox-ы уже есть «из коробки» и работа с ними ничем не отличается от работы с single-consumer mbox-ом.

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

v.5.5.1

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

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

Если кому-то еще интересны сравнения, то вот еще одно. На этот раз с кодом специалиста из Яндекса, написанного на современном C++ с использованием короутин.

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

В оригинальном коде из Хабровской статьи, насколько я могу судить, не было бенчмарков. Поэтому и я не заморачивался. Да и не та это задача, чтобы замерять производительность переключения контекстов, когда там задействован дисковый кэш и общение с сетью :)

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

Если кому-то интересно, то вот еще один пример. На этот раз демонстрируется одно из возможных решений проблемы Producer-Consumer с защитой Consumer-а от перегрузки.

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

SObjectizer обновился до версии 5.5.2. Изменений в самом SO5 нет, но добавилась экспериментальная поддержка CMake для сборки библиотеки so.5.5.2.(so,dll) и примеров (сборка тестов пока не поддерживается).

Огромная благодарность ув.тов.Alex Syrnikov за реализацию поддержки CMake.

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

Не чистое?

msvcrt — MicroSoft Visual C Run-Time

rtl — Run-Time Library

C++ RTTI — C++ Run-Time Type Information

Боюсь, только человек, который кроме real-time на C++ ничего не видел, будет видеть за RT real-time и ничего кроме real-time.

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

Зачем вы написали свои последние несколько комментариев? Сказали что-то путное, интересное или полезное?

eao197 ★★★★★
() автор топика
13 декабря 2014 г.
Ответ на: комментарий от eao197

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

Но -lrt (librt.so) используют практически все, программирующие под линукс

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

Блин, нужно срочно в каком-нибудь внутреннем пространстве имен задействовать еще какую-нибудь спорную аббревиатуру. Типа xml, soa, rip, fuckoff и т.д. Путного все равно никто ничего не скажет, но зато тема будет на плаву держаться и привлекать внимание.

eao197 ★★★★★
() автор топика
26 января 2015 г.

Подготовлена еще одна статья, знакомящая читателя с ключевыми особенностями SObjectizer-а на простом примере. Серьезного знания C++ и/или SObjectizer не требуется, материал расчитан на широкий круг читателей: "Разбор примера простой реализации дедлайнов для сообщений"

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

Нет. У меня в распоряжении Win и Linux (под виртуалкой). На этом и гоняю.

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