Погружение в SObjectizer 5.5. Вводная часть

217
Погружение в SObjectizer-5.5 SObjectizer Team, февраль 2015 Вводная часть

Transcript of Погружение в SObjectizer 5.5. Вводная часть

Page 1: Погружение в SObjectizer 5.5. Вводная часть

Погружение в SObjectizer-5.5

SObjectizer Team, февраль 2015

Вводная часть

Page 2: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

О чем пойдет речь?

Page 3: Погружение в SObjectizer 5.5. Вводная часть

О чем пойдет речь?

Об инструменте длямногопоточного программирования.

SObjectizer Team, февраль 2015

Page 4: Погружение в SObjectizer 5.5. Вводная часть

О чем пойдет речь?

Об инструменте длямногопоточного программирования.

Которое считается сложным...

SObjectizer Team, февраль 2015

Page 5: Погружение в SObjectizer 5.5. Вводная часть

О чем пойдет речь?

Об инструменте длямногопоточного программирования.

Которое считается сложным.Не просто сложным,

SObjectizer Team, февраль 2015

Page 6: Погружение в SObjectizer 5.5. Вводная часть

О чем пойдет речь?

Об инструменте длямногопоточного программирования

Которое считается сложным.Не просто сложным,а ОЧЕНЬ СЛОЖНЫМ занятием.

SObjectizer Team, февраль 2015

Page 7: Погружение в SObjectizer 5.5. Вводная часть

Ведь постоянно иметь дело cнизкоуровневыми примитивами вроде:

SObjectizer Team, февраль 2015

Page 8: Погружение в SObjectizer 5.5. Вводная часть

Ведь постоянно иметь дело cнизкоуровневыми примитивами вроде:

● native threads● critical sections, semaphores, mutexes, condition

variables, monitors● thread local storages● atomic variables, spinlocks...

SObjectizer Team, февраль 2015

Page 9: Погружение в SObjectizer 5.5. Вводная часть

Ведь постоянно иметь дело с низкоуровневыми примитивами вроде:

● native threads● critical sections, semaphores, mutexes, condition variables,

monitors● thread local storages● atomic variables, spinlocks...

И последствиями их применения в виде тупиков и гонок - это же очень сложно...

SObjectizer Team, февраль 2015

Page 10: Погружение в SObjectizer 5.5. Вводная часть

Ведь постоянно иметь дело cнизкоуровневыми примитивами вроде:

● native threads● critical sections, semaphores, mutexes, condition variables,

monitors● thread local storages● atomic variables, spinlocks...

И последствиями их применения в видетупиков и гонок - это же очень сложно...

Правильно?SObjectizer Team, февраль 2015

Page 11: Погружение в SObjectizer 5.5. Вводная часть

Правильно!

SObjectizer Team, февраль 2015

Page 12: Погружение в SObjectizer 5.5. Вводная часть

Правильно!

Однако, при использовании

SObjectizer...

SObjectizer Team, февраль 2015

Page 13: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Мы практически ни с чем из перечисленного

не сталкиваемся

Page 14: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer позволяет организоватьмногопоточное приложение в видесовокупности объектов-агентов.

SObjectizer Team, февраль 2015

Page 15: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer позволяет организоватьмногопоточное приложение в видесовокупности объектов-агентов.

SObjectizer Team, февраль 2015

Взаимодействующих друг с другомтолько посредством

асинхронных сообщений.

Page 16: Погружение в SObjectizer 5.5. Вводная часть

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

SObjectizer Team, февраль 2015

Page 17: Погружение в SObjectizer 5.5. Вводная часть

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

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

SObjectizer Team, февраль 2015

Page 18: Погружение в SObjectizer 5.5. Вводная часть

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

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

Эта защита выполняется автоматическисамим SObjectizer-ом!

SObjectizer Team, февраль 2015

Page 20: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

SObjectizer Team, февраль 2015

Page 21: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

Потому что SObjectizer создавалсяи под ее влиянием...

SObjectizer Team, февраль 2015

Page 22: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

Потому что SObjectizer создавалсяи под ее влиянием...

При этом SObjectizer - это небольшая C++ библиотека, в зону ответственности которой входят:

SObjectizer Team, февраль 2015

Page 23: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

Потому что SObjectizer создавалсяи под ее влиянием...

При этом SObjectizer - это небольшая C++ библиотека, в зону ответственности которой входят:

SObjectizer Team, февраль 2015

● доставка сообщений внутри одного процесса и

Page 24: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

Потому что SObjectizer создавалсяи под ее влиянием...

При этом SObjectizer - это небольшая C++ библиотека, в зону ответственности которой входят:

SObjectizer Team, февраль 2015

● доставка сообщений внутри одного процесса и● предоставление рабочего контекста агентам, плюс

Page 25: Погружение в SObjectizer 5.5. Вводная часть

Да! Это очень напоминает Actor Model

Потому что SObjectizer создавалсяи под ее влиянием...

При этом SObjectizer - это небольшая C++ библиотека, в зону ответственности которой входят:

SObjectizer Team, февраль 2015

● доставка сообщений внутри одного процесса и● предоставление рабочего контекста агентам, плюс● тонкая настройка всего этого дела

Page 26: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

У нас не было задачи создатьеще один Erlang,

со своим компилятором,стандартными библиотеками и

средой исполнения

Page 27: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer вообще родился тогда, когда за пределами Ericsson о Erlang мало кто знал.

SObjectizer Team, февраль 2015

Page 28: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer вообще родился тогда, когда за пределами Ericsson о Erlang мало кто знал.

SObjectizer Team, февраль 2015

В 1996-м в Гомельском КБ Системного Программирования появилась первая версия SCADA Objectizer.

Page 29: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer вообще родился тогда, когда за пределами Ericsson о Erlang мало кто знал.

SObjectizer Team, февраль 2015

В 1996-м в Гомельском КБ Системного Программирования появилась перваяверсия SCADA Objectizer.

Это был инструмент для задач АСУ ТП,в котором агенты отсылали друг другу

асинхронные сообщения.

Page 30: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer вообще родился тогда, когда за пределами Ericsson о Erlang мало кто знал.

SObjectizer Team, февраль 2015

В 1996-м в Гомельском КБ Системного Программирования появилась перваяверсия SCADA Objectizer.

Это был инструмент для задач АСУ ТП,в котором агенты отсылали друг другу

асинхронные сообщения.

А контекст для их обработки обеспечивался диспетчером.

Page 31: Погружение в SObjectizer 5.5. Вводная часть

В 2000-м разработка SCADA Objectizer прекратилась, коллектив распался.

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

SObjectizer Team, февраль 2015

Page 32: Погружение в SObjectizer 5.5. Вводная часть

В 2000-м разработка SCADA Objectizer прекратилась, коллектив распался.

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

SObjectizer Team, февраль 2015

Поэтому, когда в 2001-м уже в компании Интервэйл бывшие разработчики SCADA

Objectizer реализовали многопоточное GUI-приложение, работающее с внешним

оборудованием...

Page 33: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

...то оказалось, что в нем живет примитивная и сильно урезанная версия SCADA Objectizer

Page 34: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

...то оказалось, что в нем живет примитивная и сильно урезанная версия SCADA Objectizer

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

Page 35: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

...то оказалось, что в нем живет примитивная и сильно урезанная версия SCADA Objectizer

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

Так в 2002-м появился SObjectizer.

Page 36: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Page 37: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:

Page 38: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:● передачи SMS/USSD трафика;

Page 39: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:● передачи SMS/USSD трафика;● обслуживания финансовых транзакций;

Page 40: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:● передачи SMS/USSD трафика;● обслуживания финансовых транзакций;● мониторинга параметров ПО.

Page 41: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:● передачи SMS/USSD трафика;● обслуживания финансовых транзакций;● мониторинга параметров ПО;

В 2006-м открыт на SourceForge как OpenSource проект под BSD-лицензией.

Page 42: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Долгое время SObjectizer был внутренним инструментом компании Интервэйл.

Использовался в разработке систем:● передачи SMS/USSD трафика;● обслуживания финансовых транзакций;● мониторинга параметров ПО.

В 2006-м открыт на SourceForge как OpenSource проект под BSD-лицензией.

С 2013-го развивается на SourceForge полностью как самостоятельный,

независимый от Интервэйл проект.

Page 43: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

За время своего существования SObjectizer несколько раз полностью переписывался.

Page 44: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

За время своего существования SObjectizer несколько раз полностью переписывался.

Далее речь пойдет о пятом поколении SObjectizer, разработка которого началась в 2010-м.

Page 45: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

За время своего существования SObjectizer несколько раз полностью переписывался.

Далее речь пойдет о пятом поколении SObjectizer, разработка которого началась в 2010-м.

А более конкретно - о версии 5.5.3, выпущеннойв феврале 2015-го.

Page 46: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Вся работа в SObjectizer происходит внутриSObjectizer Environment.

Page 47: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Вся работа в SObjectizer происходит внутриSObjectizer Environment.

SObjectizer Environment - это контейнер, содержащий SObjectizer Run-Time, кооперации агентов, почтовые ящики для обмена сообщениями, диспетчеры и таймерную нить.

Page 48: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Вся работа в SObjectizer происходит внутриSObjectizer Environment.

SObjectizer Environment - это контейнер, содержащий SObjectizer Run-Time, кооперации агентов, почтовые ящики для обмена сообщениями, диспетчеры и таймерную нить.

Можно создать несколько экземпляровSObjectizer Environment. Каждый из них будет

работать независимо от других.

Page 49: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

SObjectizer Environment создается функциейso_5::launch().

Page 50: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

SObjectizer Environment создается функциейso_5::launch().

Внутри Environment so_5::launch() запускает экземпляр SObjectizer Run-Time и возвращает управление после его останова.

Page 51: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

SObjectizer Environment создается функциейso_5::launch().

Внутри Environment so_5::launch() запускает экземпляр SObjectizer Run-Time и возвращает управление после его останова.

Что именно будет происходить внутри запущенного Run-Time определяется пользовательской стартовой функцией.

Page 52: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

SObjectizer Environment создается функциейso_5::launch().

Внутри Environment so_5::launch() запускает экземпляр SObjectizer Run-Time и возвращает управление после его останова.Что именно будет происходить внутри запущенного Run-Time определяется пользовательской стартовой функцией.

В случае ошибок so_5::launch() выбрасывает исключения.

Page 53: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

Page 54: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

Главный заголовочный файл со всеми нужными определениями.

Page 55: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

Стартовая функция, которая отвечает за запуск прикладной логики приложения.

Page 56: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

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

Page 57: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

Порождение Environment, запуск Run-Time и вызов стартовой функции init. Возврат из launch() произойдет когда завершат работу созданные внутри init() прикладные агенты.

Page 58: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Выглядит это так:#include <iostream>

#include <so_5/all.hpp>

void init( so_5::rt::environment_t & env ) { ... }

int main(){ try { so_5::launch( &init ); } catch( const std::exception & x ) { std::cerr << "Exception: " << x.what() << std::endl; }}

Обработка ошибок, информирование о которых выполняется посредством исключений.

Page 59: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Внутри стартовой функции обычно создается одна или несколько коопераций с прикладными агентами.

Page 60: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Внутри стартовой функции обычно создается одна или несколько коопераций с прикладными агентами.

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

Page 61: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Внутри стартовой функции обычно создается одна или несколько коопераций с прикладными агентами.

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

Например, агенты pinger и ponger, которые обмениваются друг с другом сообщениями ping и pong.

Page 62: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Внутри стартовой функции обычно создается одна или несколько коопераций с прикладными агентами.

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

Например, агенты pinger и ponger, которые обмениваются друг с другом сообщениями ping и pong.

Нет смысла отдельно в pinger-е и отдельно в ponger-е. Эти два агента должныпоявляться и исчезать одновременно.

Page 63: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Внутри стартовой функции обычно создается одна или несколько коопераций с прикладными агентами.

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

Например, агенты pinger и ponger, которые обмениваются друг с другом сообщениями ping и pong.Нет смысла отдельно в pinger-е и отдельно в ponger-е. Эти два агента должныпоявляться и исчезать одновременно.

Именно для этого и нужны кооперации!

Page 64: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

Page 65: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

Создание кооперации происходит в три этапа.

Сначала Environment создает экземпляр кооперации...

Page 66: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

Затем кооперация наполняется агентами...

Page 67: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

Затем кооперация регистрируется.

Page 68: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

У каждой кооперации должно быть уникальное имя, корректность которого проверяется внутри register_coop().

Но можно попросить SObjectizer самостоятельно выбрать имя для новой кооперации.

Page 69: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Создание кооперации с двумя агентами:

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) );

env.register_coop( std::move( coop ) );}

Создав кооперацию, стартовая функция завершает свою работу.

Но Environment продолжит работать до тех пор, пока эта кооперация не будет дерегистрирована. Либо пока не поступит команда на останов работы Environment-а.

Page 70: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что из себя представляет агент?

Page 71: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что из себя представляет агент?

Начнем с самого простого агента в этом примере.

С агента ponger.

Page 72: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что из себя представляет агент?

Начнем с самого простого агента в этом примере.

С агента ponger.

Его задача очень проста:● получать сообщения ping;● отвечать сообщениями pong.

Page 73: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что из себя представляет агент?

Начнем с самого простого агента в этом примере.

С агента ponger.

Его задача очень проста:● получать сообщения ping;● отвечать сообщениями pong.

Но сперва определим сообщения ping и pong...

Page 74: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Определение сообщений:struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

Page 75: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Определение сообщений:struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

Каждое сообщение должно быть представлено своим собственным C++ классом (структурой).

На основании информации о типе сообщения затем происходит диспетчеризация сообщений и выбор обработчиков сообщений.

Page 76: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Определение сообщений:struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

Все сообщения, которые переносят какие-либо данные внутри себя, должны быть унаследованы от общего базового типаso_5::rt::message_t.

Бывают еще и сообщения, которые информацию внутри не переносят.Это сигналы. Подробнее они рассматриваются ниже.

Page 77: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Определение сообщений:struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

SObjectizer не налагает каких-либо серьезных ограничений на то, что находится внутри сообщений.

В данном случае поля m_req и m_resp нужны только для работы демонстрационного примера. К особенностям SObjectizer они отношения не имеют.

Page 78: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Page 79: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Каждый обычный агент должен иметь свой собственный C++ класс.

Могут быть еще и необычные, т.н. ad-hoc-агенты. О них речь пойдет чуть позже.

Page 80: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Класс каждого обычного агента должен наследоваться от общего базового типа,so_5::rt::agent_t.

Page 81: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

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

Поэтому ссылка на Environment должна передаваться в конструктор агента. А оттуда - в конструктор базового типа,so_5::rt::agent_t.

Page 82: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

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

Page 83: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Агент ponger подписывается только на одно сообщение. Это сообщение типа ping, которое приходит из почтового ящика с именем “table”.Почтовый ящик при подписке должен указываться явно.А вот тип сообщения SObjectizer определяет сам по сигнатуре обработчика сообщения.

Page 84: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Метод, в котором агент обрабатывает сообщение, называется методом-обработчиком события. Или просто событием.

Page 85: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

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

Page 86: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

На сообщение ping агент отвечает отсылкой сообщения pong в почтовый ящик с именем “table”.

Page 87: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Функция so_5::send конструирует объект типа pong и отсылает его в указанный почтовый ящик.

Page 88: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Дополнительные аргументы so_5::send(), которые следуют за ссылкой на почтовый ящик, передаются в конструктор объекта сообщения.В данном случае это аргумент resp для конструктора pong.

Page 89: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger:class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &ponger::evt_ping ); }

private : const so_5::rt::mbox_t m_table;

void evt_ping( const ping & evt ) { so_5::send< pong >( m_table, evt.m_req ); }};

Агент ponger самостоятельно получает ссылку на почтовый ящик, который нужен для обмена сообщениями.В данном случае это ящик с именем “table”, который создается посредством вызова create_local_mbox().Ссылка на почтовый ящик сохраняется внутри агента.

Page 90: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &pinger::evt_pong ); }

virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); }

Page 91: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &pinger::evt_pong ); }

virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); }

Агент pinger очень похож на агента ponger-а: получает ссылку на Environment в конструкторе, создает ссылку на почтовый ящик с именем “table” и подписывается всего на одно сообщение в so_define_agent().

Page 92: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state().event( m_table, &pinger::evt_pong ); }

virtual void so_evt_start() override { so_5::send< ping >( m_table, 500 ); }

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

Page 93: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (окончание):private : const so_5::rt::mbox_t m_table;

void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); }};

Page 94: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (окончание):private : const so_5::rt::mbox_t m_table;

void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); }};

В своем событии evt_pong агент pinger либо продолжает обмен сообщениями, отсылая следующий ping.Либо, если все ping-и уже были отосланы, инициирует дерегистрацию кооперации, которой он принадлежит.

Page 95: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент pinger (окончание):private : const so_5::rt::mbox_t m_table;

void evt_pong( const pong & evt ) { if( evt.m_resp ) so_5::send< ping >( m_table, evt.m_resp - 1 ); else so_deregister_agent_coop_normally(); }};

Кооперация может быть дерегистрирована по разным причинам. В данном случае указывается, что дерегистрация выполняется нормально, как это и предполагалось прикладной логикой.

После дерегистрации кооперации с pinger-ом и ponger-ом, других работающих коопераций не останется. Environment завершит свою работу и произойдет возврат из so_5::launch().

Page 96: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Несколько слов о почтовых ящиках (mbox-ах)...

Page 97: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Несколько слов о почтовых ящиках (mbox-ах)...

В SObjectizer, в отличии от похожих инструментов, вроде Erlang, Akka или CAF, сообщение отсылается не конкретному агенту(актору), а в почтовый ящик (mbox).

Page 98: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Несколько слов о почтовых ящиках (mbox-ах)...

В SObjectizer, в отличии от похожих инструментов, вроде Erlang, Akka или CAF, сообщение отсылается не конкретному агенту(актору), а в почтовый ящик (mbox).

За mbox-ом в SObjectizer-е может скрываться как один агент, так и несколько агентов.

А может и ни одного.

Page 99: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В SObjectizer есть два типа mbox-ов:

Page 100: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В SObjectizer есть два типа mbox-ов:

Multi-Producers/Multi-Consumers mbox-ы.Похожи на “доски объявлений”. Отосланное в mbox сообщение становится доступным для всех, кто подписан на этот mbox.В примере выше продемонстрирован MPMC-mbox.

Page 101: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В SObjectizer есть два типа mbox-ов:

Multi-Producers/Multi-Consumers mbox-ы.Похожи на “доски объявлений”. Отосланное в mbox сообщение становится доступным для всех, кто подписан на этот mbox.В примере выше продемонстрирован MPMC-mbox.

Multi-Producers/Single-Consumer mbox-ы.У этих mbox-ов только один подписчик - агент, которому принадлежит MPSC-mbox.

Page 102: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Чтобы продемонстрировать особенности MPMC-mbox-ов добавим в приведенный пример еще одного агента...

Page 103: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Чтобы продемонстрировать особенности MPMC-mbox-ов добавим в приведенный пример еще одного агента...

Этот агент будет “слушать” обмен сообщениями между агентами pinger и ponger, подсчитывая количество пересланных сообщений.

Page 104: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент listener:class listener : public so_5::rt::agent_t{public : listener( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state() .event( m_table, [this]( const ping & ) { ++m_pings; } ) .event( m_table, [this]( const pong & ) { ++m_pongs; } ); }

virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; }

private : const so_5::rt::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0;};

Page 105: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент listener:class listener : public so_5::rt::agent_t{public : listener( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state() .event( m_table, [this]( const ping & ) { ++m_pings; } ) .event( m_table, [this]( const pong & ) { ++m_pongs; } ); }

virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; }

private : const so_5::rt::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0;};

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

Page 106: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент listener:class listener : public so_5::rt::agent_t{public : listener( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) , m_table( env.create_local_mbox( "table" ) ) {}

virtual void so_define_agent() override { so_default_state() .event( m_table, [this]( const ping & ) { ++m_pings; } ) .event( m_table, [this]( const pong & ) { ++m_pongs; } ); }

virtual void so_evt_finish() override { std::cout << "result: " << m_pings << "/" << m_pongs << std::endl; }

private : const so_5::rt::mbox_t m_table; unsigned int m_pings = 0; unsigned int m_pongs = 0;};

Метод so_evt_finish() является противоположностью метода so_evt_start().Он вызывается у агента непосредственно перед тем, как агент завершит свою работу.В данном случае этот метод используется для выдачи результатов.

Page 107: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Если теперь добавить listener-а в кооперацию:

Page 108: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Если теперь добавить listener-а в кооперацию:void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) ); coop->add_agent( new listener( env ) );

env.register_coop( std::move( coop ) );}

Page 109: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Если теперь добавить listener-а в кооперацию:void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) ); coop->add_agent( new listener( env ) );

env.register_coop( std::move( coop ) );}

То в конце своей работы пример напечатает:result: 501/501

Page 110: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Если теперь добавить listener-а в кооперацию:void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

coop->add_agent( new pinger( env ) ); coop->add_agent( new ponger( env ) ); coop->add_agent( new listener( env ) );

env.register_coop( std::move( coop ) );}

То в конце своей работы пример напечатает:result: 501/501

Т.е. отсылка сообщения в MPMC-mbox - это широковещательная рассылка всем подписчикам.

Page 111: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В отличии от MPMC-mbox-а, который нужно создавать вручную, MPSC-mbox-ы создаются автоматически для каждого агента.Т.е. у каждого агента есть свой собственный MPSC-mbox, который называется direct_mbox-ом.

Page 112: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В отличии от MPMC-mbox-а, который нужно создавать вручную, MPSC-mbox-ы создаются автоматически для каждого агента.Т.е. у каждого агента есть свой собственный MPSC-mbox, который называется direct_mbox-ом.

Отправленное в MPSC-mbox сообщение либо отдается владельцу mbox-а на обработку, либо выбрасывается, если владелец на сообщение не подписан.

Page 113: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В отличии от MPMC-mbox-а, который нужно создавать вручную, MPSC-mbox-ы создаются автоматически для каждого агента.Т.е. у каждого агента есть свой собственный MPSC-mbox, который называется direct_mbox-ом.

Отправленное в MPSC-mbox сообщение либо отдается владельцу mbox-а на обработку, либо выбрасывается, если владелец на сообщение не подписан.

Т.е. если два агента общаются друг с другом через direct_mbox-ы, то никто не может

“прослушать” их общение.

Page 114: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Однако, смысл существования direct_mbox-ов вовсе не в том, чтобы позволить двум агентам установить “закрытый канал” общения.

Page 115: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Однако, смысл существования direct_mbox-ов вовсе не в том, чтобы позволить двум агентам установить “закрытый канал” общения.

Direct_mbox-ы заметно эффективнее MPMC-mbox-ов, т.к. диспетчеризация сообщений для direct_mbox-ов гораздо проще и требует меньше внутренних блокировок.

Page 116: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Однако, смысл существования direct_mbox-ов вовсе не в том, чтобы позволить двум агентам установить “закрытый канал” общения.

Direct_mbox-ы заметно эффективнее MPMC-mbox-ов, т.к. диспетчеризация сообщений для direct_mbox-ов гораздо проще и требует меньше внутренних блокировок.

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

Page 117: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В обсуждавшемся выше примере с двумя агентами pinger и ponger широковещательная рассылка не нужна.

Page 118: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В обсуждавшемся выше примере с двумя агентами pinger и ponger широковещательная рассылка не нужна.

Поэтому переделаем этот пример под работу с direct_mbox-ами.

Page 119: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В обсуждавшемся выше примере с двумя агентами pinger и ponger широковещательная рассылка не нужна.

Поэтому переделаем этот пример под работу с direct_mbox-ами.

Заодно и выбросив агента listener-а.Пусть pinger и ponger сами ведут подсчет

Page 120: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В обсуждавшемся выше примере с двумя агентами pinger и ponger широковещательная рассылка не нужна.

Поэтому переделаем этот пример под работу с direct_mbox-ами.

Заодно и выбросив агента listener-а.Пусть pinger и ponger сами ведут подсчет

Ну и поменяв сообщения на сигналы

Page 121: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Сигналы - это разновидность сообщений, в которых есть лишь факт существования сообщения.

Но нет никаких данных внутри сообщения.

Page 122: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Сигналы - это разновидность сообщений, в которых есть лишь факт существования сообщения.

Но нет никаких данных внутри сообщения.

Это очень напоминает пересылку атомов в Erlang, когда отсылается

только атом, без какой-либо дополнительной информации.

Page 123: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

При использовании SObjectizer сигналы оказались настолько распространены, что для их поддержки добавлены специальные механизмы.

Page 124: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

При использовании SObjectizer сигналы оказались настолько распространены, что для их поддержки добавлены специальные механизмы.

На уровне API работа с сигналами в чем-то похожа на работу с сообщениями. В чем-то нет.

Page 125: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем сообщения ping и pong на сигналы...

Page 126: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем сообщения ping и pong на сигналы...struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

struct ping : public so_5::rt::signal_t {};

struct pong : public so_5::rt::signal_t {};

Page 127: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем сообщения ping и pong на сигналы...

Сигналы должны наследоваться отso_5::rt::signal_t и не должны содержать данных.

struct ping : public so_5::rt::message_t{ unsigned int m_req;

ping( unsigned int req ) : m_req{ req } {}};

struct pong : public so_5::rt::message_t{ unsigned int m_resp;

pong( unsigned int resp ) : m_resp{ resp } {}};

struct ping : public so_5::rt::signal_t {};

struct pong : public so_5::rt::signal_t {};

Page 128: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а...

Page 129: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_ponger_mbox( const so_5::rt::mbox_t & mbox ) { m_ponger = mbox; }

virtual void so_define_agent() override { so_default_state().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); }

Page 130: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_ponger_mbox( const so_5::rt::mbox_t & mbox ) { m_ponger = mbox; }

virtual void so_define_agent() override { so_default_state().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); }

direct_mbox становится доступен только после создания агента.Поэтому для связывания pinger-а и ponger-а потребовался отдельный метод, который будет вызываться после создания обоих агентов.

Page 131: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_ponger_mbox( const so_5::rt::mbox_t & mbox ) { m_ponger = mbox; }

virtual void so_define_agent() override { so_default_state().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); }

В метод event() передается всего один аргумент: лямбда-функция с обработчиком сигнала. В этом случае event() делает подписку на сигнал, поступающий от direct_mbox-а агента.

Page 132: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (начало):class pinger : public so_5::rt::agent_t{public : pinger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_ponger_mbox( const so_5::rt::mbox_t & mbox ) { m_ponger = mbox; }

virtual void so_define_agent() override { so_default_state().event< pong >( [this]{ ++m_pongs; so_5::send< ping >( m_ponger ); } ); }

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

Page 133: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (окончание): virtual void so_evt_start() override { so_5::send< ping >( m_ponger ); }

virtual void so_evt_finish() override { std::cout << "pongs: " << m_pongs << std::endl; }

private : so_5::rt::mbox_t m_ponger; unsigned int m_pongs = 0;};

Page 134: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Меняем агента pinger-а (окончание): virtual void so_evt_start() override { so_5::send< ping >( m_ponger ); }

virtual void so_evt_finish() override { std::cout << "pongs: " << m_pongs << std::endl; }

private : so_5::rt::mbox_t m_ponger; unsigned int m_pongs = 0;};

Отсылка сигнала выполняется той же функцией so_5::send(), что и отсылка сообщения.Но после mbox-а получателя больше никаких аргументов не требуется.

Page 135: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_pinger_mbox( const so_5::rt::mbox_t & mbox ) { m_pinger = mbox; }

virtual void so_define_agent() override { so_default_state().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); }

Аналогичным образом меняется агент ponger (начало):

Page 136: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; }

private : so_5::rt::mbox_t m_pinger; unsigned int m_pings = 0;};

Аналогичным образом меняется агент ponger (окончание):

Page 137: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

env.register_coop( std::move( coop ) );}

Создание кооперации становится более многословным:

Page 138: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

env.register_coop( std::move( coop ) );}

Создание кооперации становится более многословным:

Кроме того, здесь есть ошибка...

Page 139: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

env.register_coop( std::move( coop ) );}

Создание кооперации становится более многословным:

Кроме того, здесь есть ошибка...

Никто не остановит этих агентов!Они будут пинговать друг друга постоянно.

Page 140: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Исправим проблему, добавив еще одного агента, который завершит работу примера через одну секунду...

Page 141: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Исправим проблему, добавив еще одного агента, который завершит работу примера через одну секунду...

Поскольку агент будет обрабатывать всего одно событие, нет смысла определять отдельный класс для этого агента, переопределять в нем метод so_define_agent() и т.д.

Page 142: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Исправим проблему, добавив еще одного агента, который завершит работу примера через одну секунду...

Поскольку агент будет обрабатывать всего одно событие, нет смысла определять отдельный класс для этого агента, переопределять в нем метод so_define_agent() и т.д.

Вместо этого создадим ad-hoc-агента.Т.е. агента, описанного “по месту”, без

дополнительных формальностей.

Page 143: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

Page 144: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Page 145: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Сигнал на завершение работы.

Page 146: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Создание ad-hoc-агента.Возвращается дескриптор, через который агента можно настраивать.

Page 147: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Новый агент подписывается на единственный сигнал stop.

Page 148: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Сигнал придет на direct_mbox нового агента.

Page 149: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент для завершения примера через секунду после начала работы:

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent();stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

Обработчик этого сигнала даст приказ SObjectizer Environment завершить работу примера.

Единственная кооперация будет дерегистрирована автоматически.

Page 150: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент создан и настроен.Осталось отослать отложенный на одну секунду сигнал stop:

Page 151: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент создан и настроен.Осталось отослать отложенный на одну секунду сигнал stop:

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );

Page 152: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Ad-hoc-агент создан и настроен.Осталось отослать отложенный на одну секунду сигнал stop:

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );

Функция so_5::send_delayed отсылает отложенное на указанное время сообщение или сигнал.В данном случае сигнал stop на direct_mbox нового ad-hoc-агента через одну секунду.

Page 153: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

В итоге стартовая функция приняла вид:void init( so_5::rt::environment_t & env ){ auto coop = env.create_coop( so_5::autoname );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent(); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

Page 154: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Запускаем обновленный пример...

Page 155: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Запускаем обновленный пример...

Получаем...

pongs: 4441168pings: 4441169

Page 156: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Запускаем обновленный пример...

Получаем...

pongs: 4441168pings: 4441169

Итого больше 8M сообщений в секунду.

Page 157: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Итого больше 8M сообщений в секунду

Core i7 2.4GHz, 8GiB RAM, Win8.1 64-bit,Visual C++ 2013 64-bit

Запускаем обновленный пример...

Получаем...

pongs: 4441168pings: 4441169

Page 158: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Итого больше 8M сообщений в секунду

Core i7 2.4GHz, 8GiB RAM, Win8.1 64-bit,Visual C++ 2013 64-bit

Запускаем обновленный пример...

Получаем...

pongs: 4441168pings: 4441169

Это хорошо, но на каком контексте работают агенты в данном примере?

Page 159: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Все агенты работают на одной общей рабочей нити!

Page 160: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Все агенты работают на одной общей рабочей нити!

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

Page 161: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Все агенты работают на одной общей рабочей нити!

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

Но кто выбирает рабочий контекст для агентов?И как привязать агента к другому контексту?

Page 162: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Все агенты работают на одной общей рабочей нити!

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

Но кто выбирает рабочий контекст для агентов?И как привязать агента к другому контексту?

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

Page 163: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Все агенты работают на одной общей рабочей нити!

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

Но кто выбирает рабочий контекст для агентов?И как привязать агента к другому контексту?

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

Как это и произошло в данном примере.

Page 164: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Для этих агентов получается что-то вроде кооперативной многозадачности. Если кто-то стал “тормозить”, то “тормозить” начинают и остальные.

Page 165: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Для этих агентов получается что-то вроде кооперативной многозадачности. Если кто-то стал “тормозить”, то “тормозить” начинают и остальные.

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

привязать своих агентов к этим диспетчерам.

Page 166: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Page 167: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Для этого создадим диспетчера active_obj и привяжем агентов к нему.

Page 168: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Для этого создадим диспетчера active_obj и привяжем агентов к нему.

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

Page 169: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого ничего не нужно менять в агентах...

Page 170: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого ничего не нужно менять в агентах...

Изменения затронут только стартовую функцию.

Page 171: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Привязка агентов к разным диспетчерам:void init( so_5::rt::environment_t & env ){ env.add_dispatcher_if_not_exists( "active_obj", &so_5::disp::active_obj::create_disp );

auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_disp_binder("active_obj") );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent( so_5::rt::create_default_disp_binder() ); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

Page 172: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Привязка агентов к разным диспетчерам:void init( so_5::rt::environment_t & env ){ env.add_dispatcher_if_not_exists( "active_obj", &so_5::disp::active_obj::create_disp );

auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_disp_binder("active_obj") );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent( so_5::rt::create_default_disp_binder() ); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

Просьба создать диспетчера с активными объектами под именем “active_obj”. Если такого диспетчера еще нет, то он будет создан с помощью указанной фабрики.

Page 173: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Привязка агентов к разным диспетчерам:void init( so_5::rt::environment_t & env ){ env.add_dispatcher_if_not_exists( "active_obj", &so_5::disp::active_obj::create_disp );

auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_disp_binder("active_obj") );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent( so_5::rt::create_default_disp_binder() ); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

Указание кооперации о том, что основным диспетчером для ее агентов будет диспетчер с именем “active_obj”.

Page 174: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Привязка агентов к разным диспетчерам:void init( so_5::rt::environment_t & env ){ env.add_dispatcher_if_not_exists( "active_obj", &so_5::disp::active_obj::create_disp );

auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_disp_binder("active_obj") );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent( so_5::rt::create_default_disp_binder() ); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

Агенты pinger и ponger добавляются в кооперацию без каких-либо дополнительных инструкций. Значит они будут привязаны к тому диспетчеру, который для кооперации считается основным диспетчером. В данном случае это будет диспетчер с именем “active_obj”.

Page 175: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Привязка агентов к разным диспетчерам:void init( so_5::rt::environment_t & env ){ env.add_dispatcher_if_not_exists( "active_obj", &so_5::disp::active_obj::create_disp );

auto coop = env.create_coop( so_5::autoname, so_5::disp::active_obj::create_disp_binder("active_obj") );

auto a_pinger = coop->add_agent( new pinger( env ) ); auto a_ponger = coop->add_agent( new ponger( env ) );

a_pinger->set_ponger_mbox( a_ponger->so_direct_mbox() ); a_ponger->set_pinger_mbox( a_pinger->so_direct_mbox() );

struct stop : public so_5::rt::signal_t {};

auto stopper = coop->define_agent( so_5::rt::create_default_disp_binder() ); stopper.event< stop >( stopper.direct_mbox(), [&env]{ env.stop(); } );

env.register_coop( std::move( coop ) );

so_5::send_delayed< stop >( env, stopper.direct_mbox(), std::chrono::seconds(1) );}

А вот для агента stopper-а отдельная рабочая нить не нужна. Поэтому этот объект явным образом привязывается к диспетчеру SObjectizer по умолчанию.Если такого прямого указания не сделать, то для агента будет выполнена привязка к основному диспетчеру кооперации.

Page 176: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что получается после запуска обновленного примера?

Page 177: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что получается после запуска обновленного примера?

pings: pongs: 12346231234624

Page 178: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что получается после запуска обновленного примера?

pings: pongs: 12346231234624

Упс… Или так и должно быть?

Page 179: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что получается после запуска обновленного примера?

pings: pongs: 12346231234624

Упс… Или так и должно быть?

Это, действительно упс. Но так и должно быть

Page 180: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что получается после запуска обновленного примера?

pings: pongs: 12346231234624

Упс… Или так и должно быть?

Это, действительно упс. Но так и должно быть Могло бы быть и еще страшнее

Page 181: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что же произошло?

pings: pongs: 12346231234624

Page 182: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что же произошло?

pings: pongs: 12346231234624

Агенты pinger и ponger стали работать на разных нитях и конкурировать за доступ к std::cout. В результате этой конкуренции вывод в std::cout перемешался. Мог бы перемешаться еще больше. А мог бы и не перемешаться вовсе. Многопоточность…

Page 183: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что еще произошло?

pings: pongs: 12346231234624

Page 184: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что еще произошло?

pings: pongs: 12346231234624

Упала общая производительность примера.Если на одной нити был показан результат в8M сообщений в секунду, то на двух нитях - всего 2M сообщений.

Page 185: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Что еще произошло?

pings: pongs: 12346231234624

Упала общая производительность примера.Если на одной нити был показан результат в8M сообщений в секунду, то на двух нитях - всего 2M сообщений.

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

дорогостоящая операция.

Page 186: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но что изменилось в самих агентах?

Page 187: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но что изменилось в самих агентах?

Ничего.

Page 188: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger дляодной рабочей нити:

class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_pinger_mbox( const so_5::rt::mbox_t & mbox ) { m_pinger = mbox; }

virtual void so_define_agent() override { so_default_state().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); }

virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; }

private : so_5::rt::mbox_t m_pinger; unsigned int m_pings = 0;};

Page 189: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Агент ponger дляодной рабочей нити:

class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_pinger_mbox( const so_5::rt::mbox_t & mbox ) { m_pinger = mbox; }

virtual void so_define_agent() override { so_default_state().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); }

virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; }

private : so_5::rt::mbox_t m_pinger; unsigned int m_pings = 0;};

Агент ponger длядвух рабочих нитей:

class ponger : public so_5::rt::agent_t{public : ponger( so_5::rt::environment_t & env ) : so_5::rt::agent_t( env ) {}

void set_pinger_mbox( const so_5::rt::mbox_t & mbox ) { m_pinger = mbox; }

virtual void so_define_agent() override { so_default_state().event< ping >( [this]{ ++m_pings; so_5::send< pong >( m_pinger ); } ); }

virtual void so_evt_finish() override { std::cout << "pings: " << m_pings << std::endl; }

private : so_5::rt::mbox_t m_pinger; unsigned int m_pings = 0;};

Page 190: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Page 191: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Поэтому им все равно, на каком контексте они работают.

Page 192: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Поэтому им все равно, на каком контексте они работают.

А задачей SObjectizer-а является предоставление программисту возможности

выбрать нужный ему контекст путем привязки агентов к соответствующим

диспетчерам.

Page 193: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

Page 194: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

● one_thread. Запускает всех агентов на одной общей рабочей нити;

Page 195: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

● one_thread. Запускает всех агентов на одной общей рабочей нити;● active_obj. Предоставляет каждому агенту отдельную нить в

единоличное пользование;

Page 196: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

● one_thread. Запускает всех агентов на одной общей рабочей нити;● active_obj. Предоставляет каждому агенту отдельную нить в

единоличное пользование;● active_group. Предоставляет отдельную нить в единоличное

пользование группе объектов;

Page 197: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

● one_thread. Запускает всех агентов на одной общей рабочей нити;● active_obj. Предоставляет каждому агенту отдельную нить в

единоличное пользование;● active_group. Предоставляет отдельную нить в единоличное

пользование группе объектов;● thread_pool. Выделяет агентам нити из пула рабочих нитей. Агенты

могут мигрировать с одной рабочей нити на другую. Но агент не может работать на двух рабочих нитях одновременно;

Page 198: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Для этого в SObjectizer есть целый ряд готовых диспетчеров “из коробки”:

● one_thread. Запускает всех агентов на одной общей рабочей нити;● active_obj. Предоставляет каждому агенту отдельную нить в

единоличное пользование;● active_group. Предоставляет отдельную нить в единоличное

пользование группе объектов;● thread_pool. Выделяет агентам нити из пула рабочих нитей. Агенты

могут мигрировать с одной рабочей нити на другую. Но агент не может работать на двух рабочих нитях одновременно;

● adv_thread_pool. Выделяет агентам нити из пула рабочих нитей. Агенты могут и мигрировать с одной рабочей нити на другую, и работать сразу на нескольких (при условии, что их обработчики событий объявлены thread safe).

Page 199: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

Page 200: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Page 201: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:

Page 202: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:● один one_thread диспетчер для агента-клиента AMQP;

Page 203: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:● один one_thread диспетчер для агента-клиента AMQP;● один thread_pool диспетчер для обработки прочитанных из AMQP-

очередей запросов;

Page 204: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:● один one_thread диспетчер для агента-клиента AMQP;● один thread_pool диспетчер для обработки прочитанных из AMQP-

очередей запросов;● один active_obj диспетчер для агентов, выполняющих работу с СУБД;

Page 205: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:● один one_thread диспетчер для агента-клиента AMQP;● один thread_pool диспетчер для обработки прочитанных из AMQP-

очередей запросов;● один active_obj диспетчер для агентов, выполняющих работу с СУБД;● еще один active_obj диспетчер для агентов, работающих с

подключенными к компьютеру HSM-ами;

Page 206: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

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

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

Например:● один one_thread диспетчер для агента-клиента AMQP;● один thread_pool диспетчер для обработки прочитанных из AMQP-

очередей запросов;● один active_obj диспетчер для агентов, выполняющих работу с СУБД;● еще один active_obj диспетчер для агентов, работающих с

подключенными к компьютеру HSM-ами;● и еще один thread_pool диспетчер для агентов, следящих за всей этой

анархией

Page 207: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Page 208: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:

Page 209: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;

Page 210: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;

Page 211: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;

Page 212: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;● дочерние кооперации;

Page 213: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;● дочерние кооперации;● обработка выпущенных агентами наружу

исключений;

Page 214: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;● дочерние кооперации;● обработка выпущенных агентами наружу

исключений;● тонкая настройка параметров Run-Time и пр...

Page 215: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;● дочерние кооперации;● обработка выпущенных агентами наружу исключений;● тонкая настройка параметров Run-Time и пр...

Будут рассмотрены при дальнейшем погружении

Page 216: Погружение в SObjectizer 5.5. Вводная часть

SObjectizer Team, февраль 2015

Но и это еще не все, что есть в SObjectizer...

Такие важные вещи, как:● состояния агентов;● периодические сообщения;● синхронное взаимодействие агентов;● дочерние кооперации;● обработка выпущенных агентами наружу исключений;● тонкая настройка параметров Run-Time и пр...

Будут рассмотрены при дальнейшем погружении Вводная же часть закончена.

Page 217: Погружение в SObjectizer 5.5. Вводная часть

Дополнительная информация:

Сайт проекта: http://sourceforge.net/projects/sobjectizer

Документация: http://sourceforge.net/p/sobjectizer/wiki/

Форум: http://sourceforge.net/p/sobjectizer/discussion/

Google-группа: https://groups.google.com/forum/#!forum/sobjectizer