Здравствуйте, remark, Вы писали:
R>Состояние, конечно, в первую очередь определяет поведение. Но для реализации поведения данного состояния могут понадобиться данные. R>В твоём примере очередь должна относиться не к состоянию, а к самому объекту. А вот канал относится уже исключительно к состоянию st_connected. R>А что будет, если я в состоянии st_disconnected вызову какой-то метод канала — ничего хорошего. И это логическая ошибка. Т.е. прграммист скорее всего не хотел это написать — не хотел, что бы в состоянии st_disconnected происходили какие-либо вызовы канала.
Во-первых, обращения к каналу в состоянии st_disconnected, скорее всего, все равно потребуются. Хотя бы для инициирования переподключения
Во-вторых, в SObjectizer я бы выделил канал в другого агента И так на самом деле и происходит. В составе SObjectizer есть транспортные агенты (для работы с SOP и с RAW-каналами (a_cln_channel_t, a_raw_cln_channel_t)), которые в своем состояние st_disconnected дергают свой атрибут-канал для восстановления подключения. Когда подключение восстанавливается, они отсылают сообщение об этом. Если агент, занимающийся обработкой транзкций заинтересован в этом сообщении, то он подписывается на это сообщение.
Т.е. я не могу припомнить ситуаций, когда бы внутри объектов-агентов, какие-то атрибуты были бы восстребованы только в одном состоянии.
E>>В качестве проверки такой кодогенерации был затеян проект RuCodeGen
. Пока нет точного определения самого DSL (только приблизительные наметки).
R>"А вот это попробуйте" R>Такая мысль у меня тоже возникла при виде всех этих макросов в коде
Я когда стал обдумывать DSL для описания агентов еще задумался о том, чтобы портировать SObjectizer в Ruby
Так что сейчас думаю, как бы этот DSL использовать одновременно и для Ruby-классов и для C++. Пока получается что-то вроде:
class SomeAgent < So4::Rt::Agent
# Событие, которое получает event_data. Приоритет и подписка определяется в динамике.
so4_event :evt_1 do |event_data|
# Код обработчика события.
...
end# Событие, которое не получает вообще никаких аргументов.
so4_event :evt_2 do ... end# Событие, которое получает и event_data и сообщение.
# Сразу же определяется инцидент и приоритет.
so4_event :evt_3,
:msg => Start, :owner => :starter, # Инцидентом является сообщение starter.Start.
:priority => 1 do |event_data, msg|
# Код обработчика события...end# Распределение событий по состояниям.
so4_state :st_initial,
:events => [ :evt_1 ]
so4_state :st_normal,
:events => [ :evt_2, evt_3 ],
:on_enter => :on_enter_st_shutdown # Для Ruby здесь даже можно блок кода определить.end
В общем, есть впечатление, что в Ruby SObjectizer использовать даже удобнее было бы
Кстати, что-то вроде соц.опроса. Представь, что ты присматривался бы к использованию SObjectizer. И увидел бы, что тебе нужно делать описания агентов вот в таком Ruby DSL. Отпугнуло бы это тебя?
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, remark, Вы писали:
R>Забавно. Типа "ну вы вообще конечно начинайте готовиться к завершению программы, но процесс всё равно умрёт неожиданно"
В реальности у нас есть проектик so_sysconf (который позволяет формировать SObjectizer-приложение из кубиков-DLL как из конструктора Lego). Там есть такая задача. Решается она следующим образом -- если кому-то нужно выполнить какие-то действия перед завершением приложения, то этот агент регистрируется у sysconf-а. При начале shutdown-а всем таким агентам sysconf отсылает специальное сообщение. Агент, получив его, выполняет необходимые ему действия, а по их завершению дерегистрируется у sysconf-а. Когда sysconf видит, что все агента дерегистрировались, он выполняет реальный shutdown. Здесь есть еще одно преимущество -- агенты могут выполнять свой shutdown параллельно.
R>Я об этом и говорю, что синхронный lock-подход на критический секциях по определению будет связан с дедлоками. Эту проблему не решить вообще. Все кто занимается синхронным взаимодействием об этом прекрасно осведомлены.
Так вот дело в том, что если SObjectizer не будет такие дедлоки диагностировать и преодолевать, то работа с их наличием будет не веселой. Они же будут эпизодическими и часто их повторение в тестовых условиях будет крайне затруднено.
А если заставить SObjectizer такие дедлоки диагностировать, то затраты на определение дедлока могут быть слишком высокими.
Так мне пока кажется.
E>>Настораживает меня фраза "все подписчики обработали сообщение". Имхо, если речь заходит о синхронном взаимодействии. то оно не может быть широковещательным, а только целенаправленным (адресным).
R>Почему? Опять же пример с валидацией текста.
Мне интересно, что делать, если синхронно обрабатывающие сообщения подписчики начнут возвращать свои данные в ответ. Как все эти ответы агрегировать? Если же получаетель один, то и проблем с агрегацией нет.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Это ппц... 2 дня назад придумал ЭТО. Ну почти это... Уже код льётся рекой и тут натыкаюсь на статью.... даже не знаю что теперь делать. Наверное найду что-то меня не устраивающее и пойду писать дальше
Здравствуйте, RealFduch, Вы писали:
RF>Это ппц... 2 дня назад придумал ЭТО. Ну почти это... Уже код льётся рекой и тут натыкаюсь на статью.... даже не знаю что теперь делать. Наверное найду что-то меня не устраивающее и пойду писать дальше
Если найдешь что-нибудь плохое, поделись впечатлениями, плз. Попробуем исправить.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>В целом я понял. Да, если будет типизация, то не будет связи с внешними системами, и не будет возможности отсылать сообщения в систему вручную.
E>Вот именно.
E>Это так. Для каждого сообщения задекларированного через SOL4_MSG_START/FINISH рантайм умеет создавать динамически объекты по необходимости (при получении этого сообщения по SOP). Отсюда и ограничения: сообщение в SObjectizer должно иметь конструктор по-умолчанию. В динамически созданный объект сообщения SObjectizer способен помещать значения полей, перечисленных в макросах SOL4_MSG_FIELD. Собственно, эти макросы и нужны для того, чтобы сделать сообщение доступным через SOP.
Я SOL4_MSG_START сразу не заметил.
Тогда у меня 2 вопроса:
1. Зачем описывать сам класс сообщения отдельно. Можно обойтись только SOL4_MSG_START, который заодно будет создавать и описание класса. Это, конечно, немного "урезает" возможности сообщений, т.е. в них будет нельзя добавить своего кода. Но в некоторых местах дополнительные ограничения идут только на пользу.
Иначе, во-первых, дублирование со всеми вытекающими.
Во-вторых, не очень прозрачные возможности, типа добавить какой-то член в класс сообщения, но не описать его в SOL4_MSG_START.
2. Отпадают все плюсы использования текстовых идентификаторов для сообщений, о которых ты писал! Если рантайм может преобразовывать сообщения в/из текстового представления, то в программе можно использовать исключительно типы в качестве идентификаторов сообщений. Но при этом не теряется возможность обмена с внешними подсистемами и "ручного" ввода сообщений внутрь системы.
R>>А как насчёт наследования строковых идентификаторов? R>>У меня была такая идея: E><...код поскипан...> R>>Я так понимаю. что когда ты говоришь "важен сам факт наличия сообщения, а данные не важны", то фактически это означет, что важна реакция на некий базовый тип сообщения, а не на производный.
E>Вероятно ты говоришь третьем варианте (с полиморфизмом), который я описал чуть выше.
Да, только я имею в виду, что при варианте с наследованием классов сообщений и не надо будет таких извращений:
E>* агент-коммуникатор способен работать с любыми сообщениями для маршаллинга/демаршаллинга, используя для этого информацию из системного словаря SObjectizer;
Подписываемся на базовый класс сообщений.
При этом как сам базовый класс, так и ран-тайм предоставляет некоторые базовые функции для работы с этим сообщением.
E>* некий агент способен обрабатывать разнотипные сообщения, если ему не важно содержимое этих сообщений, а важен сам факт их наличия;
Это я не очень понял что значит. Но возможно тоже можно решить с помощью подписки на некоторые классы сообщений.
E>* в некоторых случаях агент способен обрабатывать сообщения, производные от некоторого базового типа (обычный полиморфизм и работа через базовый интерфейс).
Подписываемся на этот базовый класс.
При этом отпадает необходимость подписываться на неизвестные типы сообщений и т.д.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, remark, Вы писали:
E>>>Наличие же единственного SObjectizer Run-Time, с другой стороны, сильно упрощает использование SObjectizer. Не болит голова о том, в каком Run-Time агент зарегистрирован, в какой Run-Time нужно отсылать сообщения. И нет вопросов о том, что делать, если агент должен одновременно входить в несколько Run-Time.
R>>В MPI не понятия вхождения агента в коммутатор. Да собственно нужно ли оно? Просто при отсылке сообщения можно указать идентификатор коммутатора.
E>Я не очень точно понимаю, что в SObjectizer может играть роль коммутатора. Давай я попробую расписать, как происходит отсылка и доставка простого сообщения в SObjectizer, может тогда ситуация проясниться.
E>Итак, кто-то вызывает send_msg. SObjectizer блокирует свой системный словарь в режиме read-only, проверяет наличие сообщения в системе. Если сообщение есть, то создается экземпляр заявки. После этого системный словарь разблокируется, а заявка передается диспетчеру, который помещает ее в нужную очередь.
E>Все. Диспетчеризация, как видишь, происходит в месте вызова send_msg. И, поскольку системный словарь блокируется на небольшое время, да еще в read-only режиме (т.е. допускается параллельная обработка send_msg), то особых затрат на диспетчеризацию нет (есть еще блокировка на уровне диспетчера, но она зависит от типа диспетчера).
E>Так что ни через какой централизованный коммуникатор сообщения в SObjectizer не проходят. Так что я не понимаю, как соотнести коммутаторы MPI с SObjectizer-ом.
Возможно роль коммутатора MPI может играть диспетчер SObjectizer .
Я имею в виду не столько потери производительности из-за излишней централизации, сколько логическую сторону вопроса. А именно:
Допустим в приложении есть две подсистемы, которые построены на асинхронном обмене сообщениями: прикладная подсистема приёма/отправки коротких сообщений (назавём её sms) и подсистема управления работой самого приложения (назовём её app).
Я говорю о том, что было бы неплохо иметь на эти две подсистемы 2 коммутатора асинхронных сообщений (возможно ты это называешь диспетчер). При этом у этих двух коммутаторов практически не пересекались множества отправителей/получателей (хотя такое вполне допустимо).
При этом мы получаем следующие возможности:
— агент sms_checker может подписаться только на сообщения коммутатора sms, т.к. его интересуют только они
— при попытке отправить сообщение "msg_sms_receive" на коммутатор app, выдавалась бы ошибка, что такой тип сообщения не зарегистрирован в данном коммутаторе
— агент может работать (отправлять/получать сообщения) только с коммутатором своей подсистемы, пир этом его не интересует наличие/добавление/удаление/изменение других коммутаторов
— возможность настраивать некоторые параметры только для одного коммутатора, не трогая других. Например количество рабочих потоков или приоритет работы
Это как своего рода namespace'ы в с++, которые подавляют излишную корреляцию между несвязными частями и обеспечивают большую масштабируемость
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>Состояние, конечно, в первую очередь определяет поведение. Но для реализации поведения данного состояния могут понадобиться данные. R>>В твоём примере очередь должна относиться не к состоянию, а к самому объекту. А вот канал относится уже исключительно к состоянию st_connected. R>>А что будет, если я в состоянии st_disconnected вызову какой-то метод канала — ничего хорошего. И это логическая ошибка. Т.е. прграммист скорее всего не хотел это написать — не хотел, что бы в состоянии st_disconnected происходили какие-либо вызовы канала.
E>Во-первых, обращения к каналу в состоянии st_disconnected, скорее всего, все равно потребуются. Хотя бы для инициирования переподключения E>Во-вторых, в SObjectizer я бы выделил канал в другого агента И так на самом деле и происходит. В составе SObjectizer есть транспортные агенты (для работы с SOP и с RAW-каналами (a_cln_channel_t, a_raw_cln_channel_t)), которые в своем состояние st_disconnected дергают свой атрибут-канал для восстановления подключения. Когда подключение восстанавливается, они отсылают сообщение об этом. Если агент, занимающийся обработкой транзкций заинтересован в этом сообщении, то он подписывается на это сообщение.
E>Т.е. я не могу припомнить ситуаций, когда бы внутри объектов-агентов, какие-то атрибуты были бы восстребованы только в одном состоянии.
Прошу заметить, что DisconnectedState не нужен член Socket socket_
Ну или, например, канал приёма коротких сообщений. Допустим администратор может его включать/отключать (или это происходит автоматически). В активном состоянии каналу может требоваться достаточно много ресурсов: сокет, дополнительный поток, внутрениий буфер, какие-то кэши. А в отключённом состоянии ему это всё не нужно.
E>>>В качестве проверки такой кодогенерации был затеян проект RuCodeGen
. Пока нет точного определения самого DSL (только приблизительные наметки).
R>>"А вот это попробуйте" R>>Такая мысль у меня тоже возникла при виде всех этих макросов в коде
E>Я когда стал обдумывать DSL для описания агентов еще задумался о том, чтобы портировать SObjectizer в Ruby E>Так что сейчас думаю, как бы этот DSL использовать одновременно и для Ruby-классов и для C++. Пока получается что-то вроде:
skip
E>В общем, есть впечатление, что в Ruby SObjectizer использовать даже удобнее было бы
Да вообще, сидишь прошраммируешь на с++ да всё пытаешься прикрутить к нему то, что в современных языках имеет удобную встроенную поддержку — то рефлекшн, то сериализацию, то фреймворки какие-то. Если уж на с++ программишь, то про другие языки лучше и не читать и не знать и уши затыкать, а то уж больно обидно становиться...
По поводу удобства такого DSL не скажу, так я ещё не прочуствовал насколько макросы были плохи
E>Кстати, что-то вроде соц.опроса. Представь, что ты присматривался бы к использованию SObjectizer. И увидел бы, что тебе нужно делать описания агентов вот в таком Ruby DSL. Отпугнуло бы это тебя?
Меня лично нет.
Хотя знаю людей, которых всяческие навороты отпугивают — им лучше, что бы всё по старому, по привычному.
Меня гораздо больше отпугивают вещи, которые такие DSL как раз призваны решать — а именно когда в коде есть много вещей, которые хорошо было бы описывать декларативно, но приходится описывать имепративно, да ещё зашивая в описание множество всяких не относящихся к делу вещей — например, описания множества однотипных классов-сущностей, описание структры БД в коде, написание запросов к БД и т.д.
Хотя такой DSL мог бы меня отпугнуть в след. ситуации: DSL в сторонней библиотеке, к которой нет хорошей документации, и я как раз решаю юзать е или нет. Тут DSL может отпугнуть, т.к. всё-таки всё услажняется: т.е. надо помимо кода ещё какие-то файлы писать, как-то дополнительно их обрабатывать и т.д.
А вот если например такой DSL уже используется в проекте, есть примеры, есть знающие люди, налажена компиляция DSL, то тут я только за.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, remark, Вы писали:
R>>Забавно. Типа "ну вы вообще конечно начинайте готовиться к завершению программы, но процесс всё равно умрёт неожиданно"
E> E>В реальности у нас есть проектик so_sysconf (который позволяет формировать SObjectizer-приложение из кубиков-DLL как из конструктора Lego). Там есть такая задача. Решается она следующим образом -- если кому-то нужно выполнить какие-то действия перед завершением приложения, то этот агент регистрируется у sysconf-а. При начале shutdown-а всем таким агентам sysconf отсылает специальное сообщение. Агент, получив его, выполняет необходимые ему действия, а по их завершению дерегистрируется у sysconf-а. Когда sysconf видит, что все агента дерегистрировались, он выполняет реальный shutdown. Здесь есть еще одно преимущество -- агенты могут выполнять свой shutdown параллельно.
Тоже вариант.
А если надо будет 2 таких сообщения подряд обработать? В начале обработать одно, все агенты отписываются, потом отсылается сообщение, что агентам можно заново подписываться. они снова подписываются, потом рассылается второе сообщение и агенты опять отписываются
Это же эмуляция синхронности. А если бы её поддержка была в фреймворке, то было бы проще.
R>>Я об этом и говорю, что синхронный lock-подход на критический секциях по определению будет связан с дедлоками. Эту проблему не решить вообще. Все кто занимается синхронным взаимодействием об этом прекрасно осведомлены.
E>Так вот дело в том, что если SObjectizer не будет такие дедлоки диагностировать и преодолевать, то работа с их наличием будет не веселой. Они же будут эпизодическими и часто их повторение в тестовых условиях будет крайне затруднено.
E>А если заставить SObjectizer такие дедлоки диагностировать, то затраты на определение дедлока могут быть слишком высокими.
E>Так мне пока кажется.
Тут я согласен. Имел дело с крупными проектами, которые работают по синхронному принципу и основаны на lock'ах — врагу не пожелаешь
E>>>Настораживает меня фраза "все подписчики обработали сообщение". Имхо, если речь заходит о синхронном взаимодействии. то оно не может быть широковещательным, а только целенаправленным (адресным).
R>>Почему? Опять же пример с валидацией текста.
E>Мне интересно, что делать, если синхронно обрабатывающие сообщения подписчики начнут возвращать свои данные в ответ. Как все эти ответы агрегировать? Если же получаетель один, то и проблем с агрегацией нет.
Ну это уже третий вопрос. Например:
struct Result
{
private:
long result_;
public:
void setResult(long result)
{
InterlockedExchange(&result_, result_ && result);
}
};
Все агенты после обработки дёргают Result::setResult и устанавливают свой результат обработки. При необходимости результаты можно объединять по ||
Здравствуйте, eao197, Вы писали:
R>>Фактически сейчас есть возможность отправлять синхронные сообщения:
R>>
R>>struct SyncMessageParams
R>>{
R>> int result;
R>> Event messageProcessed; // Событие, что сообщение обработано
R>> void wait(); // Ждать, пока сообщение не обработается
R>>};
R>>SyncMessageParams params;
R>>async_send("msg", ¶ms);
R>>params.wait(); // Ждём пока сообщение будет обработано
R>>if (params.result) ...;
R>>
E>Это не правильный код E>Сообщения должны быть динамически созданными объектами, удалением которых занимается сам SObjectizer.
R>>Тока единственная проблема — только инфрастуктура может знать, что все подписчики обработали сообщение, и установить Event messageProcessed. R>>Поэтому нужна хотя бы минимальная поддержка со стороны инфрастуктуры — чтобы она установила Event после того как всё подписчики обработают сообщение. Необходимость такого действия можно определять например так: если параметры сообщения отнаследованы от некого SyncParams, то значит сообщение синхронное и надо установить этот Event.
Yes! И всё-таки она есть!
class SyncResult
{
private:
Event event_;
int result_;
public:
void set(int result)
{
result_ = result;
event_.Set();
}
int waitForProcess()
{
WaitForSingleObject(event_);
return result_;
}
};
class SyncMessage
{
private:
SyncResult& sync_;
int result_;
public:
SyncMessage(SyncResult& sync)
: sync_(sync)
, result(0)
{}
void setResult(int result)
{
// По некому закону объединяем result_ и result
}
//... ~SyncMessage()
{
// Это выполняется при удалении сообщения - очевидно, что это происходит после обработки сообщения всеми подписчиками
sync_.set(result_);
}};
int main()
{
SyncResult syncResult;
so4::send("msg", new SyncMessage(syncResult));
int syncProcessResult = syncResult.waitForProcess();
}
Вся работа с потоками на месте.
Получателей может быть один или много (надо только запрограммировать закон объединения результата).
При желании (для уменьшения дедлоков) можно помимо блокируещего метода waitForProcess() добавить метод bool checkIsMessageProcessed(). Или не устанавливать Event при окончании обработки, а вызывать установленный калбэк.
Здравствуйте, remark, Вы писали:
R>Тогда у меня 2 вопроса: R>1. Зачем описывать сам класс сообщения отдельно. Можно обойтись только SOL4_MSG_START, который заодно будет создавать и описание класса. Это, конечно, немного "урезает" возможности сообщений, т.е. в них будет нельзя добавить своего кода. Но в некоторых местах дополнительные ограничения идут только на пользу. R>Иначе, во-первых, дублирование со всеми вытекающими. R>Во-вторых, не очень прозрачные возможности, типа добавить какой-то член в класс сообщения, но не описать его в SOL4_MSG_START.
Здесь несколько факторов.
Во-первых, за макросами SOL4_MSG_START/SOL4_MSG_FIELD/SOL4_MSG_FINISH скрывается достаточно много кодогенерации, которую не хочется выносить на уровень заголовочных файлов. А если заставлять пользователя описывать сообщения исключительно через макросы SOL4_MSG_*, то такое описание придется делать в заголовочных файлах -- иначе это сообщение не будет доступно в других единицах трансляции.
Во-вторых, нельзя лишать пользователя возможности добавлять собственный код в сообщения. По следующим причинам:
* в сообщении кроме конструктора по-умолчанию в подавляющем большинстве случаев приходится делать дополнительные конструкторы, чтобы создавать проинициализированный объект сообщения одной строкой:
new msg_some_action( param1, param2, param3 );
вместо:
m = new msg_some_action();
m->param1 = param1;
m->param2 = param2;
m->param3 = param3;
* в сообщении с данным следует еще определять метод checker, который сможет проверять корректность сообщения;
* в SOL4_MSG_FIELD нужно перечислять только поля простейших типов, либо типов, сериализуемых через ObjESSty. Но это очень мало для полноценной работы. Кроме того, через SOL4_MSG_FIELD нужно перечислять только поля, доступные через SOP. Очень часто сообщение вообще не должно быть доступно через SOP, но зато должно содержать поля сложных типов (указатели, в том числе и умные, STL-контейнеры, сложные пользовательские типы);
* я не хотел, чтобы SObjectizer накладывал жесткие условия на типы сообщений. Вроде наследования от общего корня. Или каких-то органичений на состав полей/методов. Ведь если этих ограничений нет, то в качестве сообщений можно использовать объекты любых типов. Даже типов, которые появились в приложении до SObjectizer-а. Например, зачем запрещать человеку отсылать в качестве сообщения std::vector, если ему это действительно нужно?
R>2. Отпадают все плюсы использования текстовых идентификаторов для сообщений, о которых ты писал! Если рантайм может преобразовывать сообщения в/из текстового представления, то в программе можно использовать исключительно типы в качестве идентификаторов сообщений. Но при этом не теряется возможность обмена с внешними подсистемами и "ручного" ввода сообщений внутрь системы.
Я думаю, что этот пункт теряет актуальность в связи с тем, что я написал выше.
R>Да, только я имею в виду, что при варианте с наследованием классов сообщений и не надо будет таких извращений:
E>>* агент-коммуникатор способен работать с любыми сообщениями для маршаллинга/демаршаллинга, используя для этого информацию из системного словаря SObjectizer;
R>Подписываемся на базовый класс сообщений. R>При этом как сам базовый класс, так и ран-тайм предоставляет некоторые базовые функции для работы с этим сообщением.
Я не хотел принципиально, чтобы для сообщений был общий корень иерархии, из которого все растет.
E>>* некий агент способен обрабатывать разнотипные сообщения, если ему не важно содержимое этих сообщений, а важен сам факт их наличия;
R>Это я не очень понял что значит.
Ну например, есть агент, который в случае какой-нибудь аварии отсылает SMS-ку куда-нибудь. Этот агент в конфиге получает информацию, что ему нужно подписаться на сообещения a_fire_monitor.msg_alarm, a_electric_power_monitor.msg_alarm, a_floor_security.msg_alarm. Каждое из этих сообщений имеет собственный тип, но для агента a_alarm_sms_sender это не важно -- он не будет анализировать их содержимое.
Еще один пример. Некий агент может собирать статистику о количестве указанных сообщений в системе за последнее время. Например, если количество сообщений msg_trx_failed за последние 15 минут превысило 20%, то нужно об этом как-то сигнализировать. Такому агенту для сбора статистики вообще безразлично, какие именно сообщения он будет мониторить.
R>Но возможно тоже можно решить с помощью подписки на некоторые классы сообщений.
Я думаю, что в вышеперечисленных случаях вообще будет проблематично выделять некоторые базовые классы сообщений.
E>>* в некоторых случаях агент способен обрабатывать сообщения, производные от некоторого базового типа (обычный полиморфизм и работа через базовый интерфейс).
R>Подписываемся на этот базовый класс.
Не нужно подписываться на базовый класс. Нужно подписываться на конкретные сообщения. Поскольку однотипных сообщений в системе может быть несколько тысяч, а интересовать нас могут всего несколько экземпляров.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, remark, Вы писали:
R>Допустим в приложении есть две подсистемы, которые построены на асинхронном обмене сообщениями: прикладная подсистема приёма/отправки коротких сообщений (назавём её sms) и подсистема управления работой самого приложения (назовём её app). R>Я говорю о том, что было бы неплохо иметь на эти две подсистемы 2 коммутатора асинхронных сообщений (возможно ты это называешь диспетчер). При этом у этих двух коммутаторов практически не пересекались множества отправителей/получателей (хотя такое вполне допустимо). R>При этом мы получаем следующие возможности: R>- агент sms_checker может подписаться только на сообщения коммутатора sms, т.к. его интересуют только они R>- при попытке отправить сообщение "msg_sms_receive" на коммутатор app, выдавалась бы ошибка, что такой тип сообщения не зарегистрирован в данном коммутаторе R>- агент может работать (отправлять/получать сообщения) только с коммутатором своей подсистемы, пир этом его не интересует наличие/добавление/удаление/изменение других коммутаторов R>- возможность настраивать некоторые параметры только для одного коммутатора, не трогая других. Например количество рабочих потоков или приоритет работы
Не понимаю, зачем все это нужно. Если две подсистемы не связаны между собой и не отсылают друг другу сообщений, то какая им разница, через один коммутатор они работают или нет? Пусть себе работают параллельно. Не зная имени агента-владельца сообщения нельзя отослать сообщение этого агента.
R>Это как своего рода namespace'ы в с++, которые подавляют излишную корреляцию между несвязными частями и обеспечивают большую масштабируемость
Аналогом namespace-ов C++ в SObjectizer является включение имени namespace из C++ в имена агентов и коопераций SObjectizer. Например, у меня есть агенты:
Здравствуйте, remark, Вы писали:
E>>Т.е. я не могу припомнить ситуаций, когда бы внутри объектов-агентов, какие-то атрибуты были бы восстребованы только в одном состоянии.
R>Вот как мне это видиться:
R>
R>Прошу заметить, что DisconnectedState не нужен член Socket socket_
А теперь представь, что все агенты в SObjectizer вынуждены менять свои состояния через создание нового объекта-состояния. Агентов могут быть сотни тысяч. А некоторые агенты могут менять свое состояние сотни раз в секунду. И это при том, что реальной очистки ресурсов будут требовать считанные единицы действительно тяжеловесных агентов.
R>Ну или, например, канал приёма коротких сообщений. Допустим администратор может его включать/отключать (или это происходит автоматически). В активном состоянии каналу может требоваться достаточно много ресурсов: сокет, дополнительный поток, внутрениий буфер, какие-то кэши. А в отключённом состоянии ему это всё не нужно.
Ну и в чем проблема? Сокет по любому придется закрывать. Вызовешь у объекта типа CSocket метод close() при смене состояния и все.
Поток уснет на каком-нибудь condition variable и никаких ресурсов требовать не будет. Кэши почистятся.
Имхо, повторное создание/уничтожение всего этого хозяйства при смене состояния будет гораздо дороже, чем однократное создание его с последующим переводом в standby/ready.
Да и SObjectizer как раз создавался для того, чтобы со своими потоками не приходилось разбираться. Так что вместо управления собственными потоками вручную лучше сделать активного агента в SObjectizer.
E>>Кстати, что-то вроде соц.опроса. Представь, что ты присматривался бы к использованию SObjectizer. И увидел бы, что тебе нужно делать описания агентов вот в таком Ruby DSL. Отпугнуло бы это тебя?
R>Меня лично нет. R>Хотя знаю людей, которых всяческие навороты отпугивают — им лучше, что бы всё по старому, по привычному. R>Меня гораздо больше отпугивают вещи, которые такие DSL как раз призваны решать — а именно когда в коде есть много вещей, которые хорошо было бы описывать декларативно, но приходится описывать имепративно, да ещё зашивая в описание множество всяких не относящихся к делу вещей — например, описания множества однотипных классов-сущностей, описание структры БД в коде, написание запросов к БД и т.д. R>Хотя такой DSL мог бы меня отпугнуть в след. ситуации: DSL в сторонней библиотеке, к которой нет хорошей документации, и я как раз решаю юзать е или нет. Тут DSL может отпугнуть, т.к. всё-таки всё услажняется: т.е. надо помимо кода ещё какие-то файлы писать, как-то дополнительно их обрабатывать и т.д. R>А вот если например такой DSL уже используется в проекте, есть примеры, есть знающие люди, налажена компиляция DSL, то тут я только за.
Спасибо за высказанное мнение.
Надеюсь, что SObjectizer таки относится к библиотекам, для которой есть хорошая документация
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, remark, Вы писали:
R>А если надо будет 2 таких сообщения подряд обработать? В начале обработать одно, все агенты отписываются, потом отсылается сообщение, что агентам можно заново подписываться. они снова подписываются, потом рассылается второе сообщение и агенты опять отписываются
Что-то я про два сообщения подряд не понял.
E>>Мне интересно, что делать, если синхронно обрабатывающие сообщения подписчики начнут возвращать свои данные в ответ. Как все эти ответы агрегировать? Если же получаетель один, то и проблем с агрегацией нет.
R>Ну это уже третий вопрос. Например:
R>
R>Все агенты после обработки дёргают Result::setResult и устанавливают свой результат обработки. При необходимости результаты можно объединять по ||
Это тривиальный случай с возвратом long-а. Он не интересен. На практике как раз синхронность требовалась когда в сообшении-запросе передавался большой объем данных, а назад требовалось получить так же сложный объект с результатами их обработки/анализа/проверки.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, remark, Вы писали:
R>Yes! И всё-таки она есть!
R>
R>class SyncResult
R>{
R>private:
R> Event event_;
R> int result_;
R>public:
R> void set(int result)
R> {
R> result_ = result;
R> event_.Set();
R> }
R> int waitForProcess()
R> {
R> WaitForSingleObject(event_);
R> return result_;
R> }
R>};
R>class SyncMessage
R>{
R>private:
R> SyncResult& sync_;
R> int result_;
R>public:
R> SyncMessage(SyncResult& sync)
R> : sync_(sync)
R> , result(0)
R> {}
R> void setResult(int result)
R> {
R> // По некому закону объединяем result_ и result
R> }
R> //...
R> ~SyncMessage()
R> {
R> // Это выполняется при удалении сообщения - очевидно, что это происходит после обработки сообщения всеми подписчиками
R> sync_.set(result_);
R> }};
R>int main()
R>{
R> SyncResult syncResult;
R> so4::send("msg", new SyncMessage(syncResult));
R> int syncProcessResult = syncResult.waitForProcess();
R>}
R>
R>
Это вариант для синхронного взаимодействия только в рамках одного процесса.
R>При желании (для уменьшения дедлоков) можно помимо блокируещего метода waitForProcess() добавить метод bool checkIsMessageProcessed().
Имхо, вместо метода checkIsMessageProcessed() лучше ввести в waitForProcess() тайм-аут ожидания результата. И выставлять тайм-аут в 0, если требуется получить результат немедленно.
R> Или не устанавливать Event при окончании обработки, а вызывать установленный калбэк.
Зачем callback, если в SObjectizer есть механизм событий/сообщений?
Это те же самые callback-и.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
ЕО>Авторы: ЕО> Евгений Охотников
ЕО>Аннотация: ЕО>Данная статья знакомит читателя с проектом SObjectizer -- инструментом для агентно-ориентированного программирования на C++. Раcсказывается о его истории, текущем состоянии и ближайших перспективах. Обсуждаются некоторые преимущества, которые дает SObjectizer, а также некоторые его недостатки и проблемы.
Статью прочитал.
Проделан не малый труд, любой уважающий себя человек ценит то что он сделал,
Но (мое ИМХО) SObjectizer — это архаизм, который уже давно с лихвой "покрывается" современным
подходом к разработке и написанными Framework'ами.
Ваше время бесспорно было в конце 90х, но на сегодняшний момент все крупные фирмы в той или иной
степени переходят с С++ на более продвинутые языки. Не возможно, да и не нужно, все написать на С# или Java, всегда будет оставаться необходимость в C++ или Assembler'ных вставках, но, заметьте,
их использование сводиться к минимуму.
Дмитрий.
Здравствуйте, Dy64, Вы писали:
D>Но (мое ИМХО) SObjectizer — это архаизм, который уже давно с лихвой "покрывается" современным D>подходом к разработке и написанными Framework'ами. D>Ваше время бесспорно было в конце 90х, но на сегодняшний момент все крупные фирмы в той или иной D>степени переходят с С++ на более продвинутые языки. Не возможно, да и не нужно, все написать на С# или Java, всегда будет оставаться необходимость в C++ или Assembler'ных вставках, но, заметьте, D>их использование сводиться к минимуму.
И?
Какого-то определенного вывода в ваших словах я, к сожалению, не увидел.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, remark, Вы писали:
R>4. Синхронные сообщения — всё-таки они нужны. Их отсутствие сужает область применения, если не в два раза, то по крайней мере на треть. R>Это всё равно как заставить у всех функций использовать возвращаемый тип только void.
Позволю себе не согласиться с автором данного тезиса. Наоборот, жестко синхронная система подобна последовательному алгоритму, только в распределенном варианте исполнения. Более того синхронность и асинхронность — это всего лишь примитивы реализации взаимодействия, обладающие разными семантиками. И только от поставленной задачи зависит какой сопсоб взаимодействия агентов (компонент, процессов, потоков и прочее.....) лучше всего выбрать.
На мой взгляд и синхронный, и асинхронный способы обладают своими недостатками и преимуществами. При любом варианте взаиммодействия имеем: в синхронном варианте — дедлоки (deadlock), в асинхронном — ливлоки (livelock). Синхронные приложения проще отлаживать (есть возможность воспроизвести поведение программы, а значит повторить ошибку). Асихронные приложения очень тяжело отлаживать, но зато в них имеется больший потенциал производительности.
Также следует заметить еще один факт. Прелесть агенто-ориентированного подхода и состоит в том, что ты позволяешь себе мыслить асинхронно, не загоняя себя в синхронные рамки. Раскладываешь все по полочкам, а потому смотришь, как эфективнее организовать схему взаимодействия объектов (агентов) на полочках.
В заключении хочу сказать. Что хоть и идея построения такой платформы достаточно старая, но думаю реализация заслуживает право на существование. Практика использования покажет живучесть системы.
Доброго времени суток.
У меня сложилось впечатление, что автор дествительно профессионал в с++. Все ниже контретно ни к кому не относиться, а является общим моим мнением в отношении программистов, которые пишут кривой работающий код.
Много раз убеждался, что прежде, чем что-то писать надо продумать архитектуру полностью на бумаге, найти аналогии в железе или в реальном мире, даже не пытаясь что-то реализовывать на компе. Примеров по этому много, например, Нейман придумал компьютер, причем в глаза его так и не увидел. Что стало с его задумкой все знают.
Я больше чем убежден, что прежде чем писать ТАКИЕ проекты надо знать как минимум логику работы
1) Процессора (выборка-исполенние)
2) Памяти
3) Контроллеров прерываний и их взаимодействие с процем
...ну и, короче, знать основы работы на НИЗАХ как и почему и хотеть(!) интересоваться этим дальше.
А именно для того, чтобы не изобретать велосипеды. Зная железо вы будете постоянно проводить аналогии с программированием наверху! Я никогда не возьму на работу программера на .NET если он не знает ассемблера, так как его грамотность в архитектуре приложений скорее всего оставляет желать лучшего. (А это самое главное, синтаксис языка — на самом последнем месте).
Заметьте все части компа работают в ассинхронном режиме, и ничего не валится. Причем некоторые моменты поистине гениальны в железе. Взять для примера хоть алгоритм работы 2-х кешей в двух ядерном процессоре — подика придумай как его на SObjectizer написать (теоретически). Я уверен все накроется или, по крайней мене, доставка сообщений будет не оптимальна. Есть замечательные слова — разделя и властвуй. У вас есть иерархический протокол сообщений с возможностью надстройки или смены протокола? Тут зашел разговор про маршрутизацию, Сразу же надо знать почему в компе ее нет, а в локальных/глобальных сетях есть. В чем плюсы и недостатки. От куда столько сетевых протоколов и как они работают. Тогда и не было бы демогогии что лучше. Это все к вопросу о велосипедах.
Не надо тут говорить, что у SObjectizer уникальная идея. я больше чем убежден (более-менее серьезный разговор это развеет) что это не так.
Несмотря на такую критику я не против такой идеи, только меня насторожило следующее: автор сказал, что у них нет идей, что делать дальше. Это значит тупик. У людей в белых халатах из Research-центров всегда есть куча идей и куча денег — нет времени это все реализовать.
Собственно интересна ранняя история такой идеи, с чего бы вдруг ей зародиться? И если она зародилась в 90, то в прежднем виде сейчас быть не должна хотя бы ради конкурентноспособности.
Здравствуйте, vip_delete, Вы писали:
_>Я больше чем убежден, что прежде чем писать ТАКИЕ проекты
Под "ТАКИМИ" понимается SObjectizer? Или вообще разработка библиотек и фреймворков?
_> надо знать как минимум логику работы _>1) Процессора (выборка-исполенние) _>2) Памяти _>3) Контроллеров прерываний и их взаимодействие с процем _>...ну и, короче, знать основы работы на НИЗАХ как и почему и хотеть(!) интересоваться этим дальше.
Это очень спорное утверждение, выходящее за рамки обсуждения SObjectizer, но все-таки можно ли его обосновать?
_>А именно для того, чтобы не изобретать велосипеды. Зная железо вы будете постоянно проводить аналогии с программированием наверху! Я никогда не возьму на работу программера на .NET если он не знает ассемблера, так как его грамотность в архитектуре приложений скорее всего оставляет желать лучшего. (А это самое главное, синтаксис языка — на самом последнем месте).
Не берусь судить о вашем опыте по найму сотрудников, но предположу, что знание ассемблера не потребуется при проектировании многоуровневого распределенного приложения. Нет, конечно же общая эрудиция и способность к перестройке мышления, которая достигается знаниями разных языков и инструментов -- это все большой плюс. Но гораздо важнее оценивать способность человека к обучению, наличие у него здавого смысла, желания работать и обучаться, возможность перестраивать свое видение проблемы в зависимости от условий.
_>Заметьте все части компа работают в ассинхронном режиме, и ничего не валится. Причем некоторые моменты поистине гениальны в железе. Взять для примера хоть алгоритм работы 2-х кешей в двух ядерном процессоре — подика придумай как его на SObjectizer написать (теоретически). Я уверен все накроется или, по крайней мене, доставка сообщений будет не оптимальна. Есть замечательные слова — разделя и властвуй. У вас есть иерархический протокол сообщений с возможностью надстройки или смены протокола? Тут зашел разговор про маршрутизацию, Сразу же надо знать почему в компе ее нет, а в локальных/глобальных сетях есть. В чем плюсы и недостатки. От куда столько сетевых протоколов и как они работают. Тогда и не было бы демогогии что лучше. Это все к вопросу о велосипедах.
Вот здесь я вообще потерял нить рассуждений.
Зачем писать на SObjectizer алгоритм работы 2-х кэшей? Для имитационного моделирования? Если так, то про какую оптимальность доставки сообщений может идти речь?
Зачем какой-то иерархический протокол доставки сообщений (с упоминанием локальных и глобальных сетей)?
Мне кажется, что этот абзац содержит в себе какие-то внутренние противоречия. И не понятно, какое отношение он имеет к велосипедам вообще и к SObjectizer в частности.
Если же вы думаете, что при разработке программного обеспечения (software) нужно искать аналогии в аппаратуре (hardware), то может быть скажете, где в аппаратуре можно найти аналогию сборки мусора (GC)?
Это я к тому, что на мой взгляд, в мире не так уж много принципиально разных идей. И какая-нибудь идея может иметь разные воплощения в разных областях, будь то software или hardware (как то асинхронное взаимодействие). Вот только совсем не факт, что какая-то реализация идеи в hardware должна становиться догмой в software.
_>Не надо тут говорить, что у SObjectizer уникальная идея. я больше чем убежден (более-менее серьезный разговор это развеет) что это не так.
А где было сказано, что SObjectizer -- это уникальная идея?
Наоборот, подчеркивалось, что многие вещи были взяты из других источников (см., например, сообщение AVC
).
А люди, знакомые с Erlang-ом сразу говорят, что SObjectizer выглядит, как попытка реализовать Erlang в C++.
Повторюсь, в мире не так уж много оригинальных идей.
Если в чем-то и есть уникальность SObjectizer-а, так это в самом факте его существования. SObjectizer -- это не фантазия, не академическая разработка, не доклад на научной конференции. Это реально существующий и использующийся инструмент. Его можно скачать, скомпилировать, запустить. Если понравиться, то взять и применить. И обсуждать, и критиковать его можно только лишь по одной, самой важной причине -- он есть.
А это позволяет заинтересовавшись SObjectizer-ом посмотреть на него пристальнее, покрутить, повертеть, примерить. Найти недостатки, указать на них. Его можно развивать. Собственно, вся цель выпуска SObjectizer в мир состоит в том, чтобы развивать его не только так, как мы это видим. Но и так, как могут увидеть и другие люди.
_>Несмотря на такую критику я не против такой идеи, только меня насторожило следующее: автор сказал, что у них нет идей, что делать дальше.
Не говорил я такого.
Я сказал:
Его возможностей (как внутреннего инструмента) вполне достаточно. Поэтому можно сказать, что нет свежих идей, которые бы дали новый толчок развитию SObjectizer.
Идеи как раз есть. Только это все наши собственные идеи. А хотелось бы услышать новые, неожиданные, из тех областей, про которые мы, возможно, даже не слышали. Чтобы в идеале кто-то взял и сказал: "Я считаю, что SObjectizer мог бы пригодиться вот здесь, но для этого нужно, чтобы он поддерживал то-то и то-то."
А мы бы в ответ: "Ух ты! А ведь действительно... Погнали!"
Но еще важнее, чтобы реализованная в SObjectizer идея была бы опробованна на практике. Чтобы не оказалось, что мы сделали фишку, предоставляющую только академический интерес.
Ну, например, время от времени возникает желание сделать сообщение-сигнал. Т.е., если сообщение A было отосланно, но еще не обработано, то повторые отсылки A не приводят к появлению новых экземпляров A. Или иногда высказываются предположение, что очереди заявок к агентам можно было бы ограничить по глубине. Скажем, стоит в очереди 2000 событий, новое не ставится, т.к. агент перегружен. Или идея перехвата сообщений с возможностью возобновления его обработки в дальнейшем. Или идея о сохранении сообщений в очередях на диске для обеспечения их гарантированной доставки...
Хочется сохранить разумный баланс между функциональностью SObjectizer и сложностью его реализации. Чтобы не превратить SObjectizer в барахолку неиспользуемых возможностей, которую очень трудно сопровождать.
_>У людей в белых халатах из Research-центров всегда есть куча идей и куча денег — нет времени это все реализовать.
Мы не люди в белых халатах из Research центров.
Интервэйл (пока) не Microsoft, не Sun, не HP, не Siemens и, тем более, не IBM. Так что у нас элементарно нет кучи денег на то, чтобы нанять 5-10 человек на полный рабочий день для клепания новых версий SObjectizer-а.
И при этом, не смотря на отсутствие белых халатов и кучи денег, времени все равно не хватает.
Если же у кого есть куча денег, которые он хочет вложить в Research, то мы с удовольствием поможем эту кучу освоить
_>Собственно интересна ранняя история такой идеи, с чего бы вдруг ей зародиться?
Ранняя история описывалась в ранней же моей статье История одного проекта. Но если этого не достаточно, то я могу сделать небольшой экскурс от истоков до сегодняшнего дня.
_>И если она зародилась в 90, то в прежднем виде сейчас быть не должна хотя бы ради конкурентноспособности.
А нынешний вид SObjectizer и так оОочень сильно отличается от того, что было в самом начале.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.