Механизм mchain-ов (сокращение от message chain), появившийся в версии 5.5.13, внезапно оказался полезным в качестве счетчика событий.
При написании тестов для SObjectizer зачастую возникает задача дождаться, пока группа агентов закончит выполнение каких-то своих операций. Т.к. агенты могут работать на разных потоках и выполнять разный объем работы, не всегда бывает просто определить этот момент. Традиционным подходом до сих пор было создание отдельного агента-наблюдателя, задачей которого было бы получение нотификаций от рабочих агентов. Принцип прост: рабочий агент после завершения работы отсылает уведомление агенту-наблюдателю, агент-наблюдатель считает нотификации и когда их количество достигает нужного значения, выполняет то, что требуется для теста (завершает работу SObjectizer-а, осуществляет какие-то проверки, инициирует следующую порцию операций и т.д.).
Оказалось, что в ряде ситуаций вместо такого агента-наблюдателя можно использовать mchain. Рабочие агенты отсылают в mchain уведомления, а кто-то просто висит на вызове so_5::receive и просто считает эти уведомления. Причем, за счет такой штуки, как handle_n(), можно вообще ничего не считать -- все это сделает сам so_5::receive.
Вот небольшой свежий пример. Нужно было дождаться момента старта агентов в двух кооперациях, после чего инициировать завершение работы SObjectizer. Агенты в своих методах so_evt_start отсылали в mchain специальное уведомление complete. А главная нить приложения просто заснула на вызове so_5::receive до тех пор, пока оба уведомления не будут прочитаны из mchain-а:
so_5::launch( [&]( so_5::environment_t & env ) { // Создаем простой mchain для получения уведомлений от агентов. auto notify_ch = env.create_mchain( so_5::make_unlimited_mchain_params() ); // Создаем две кооперации, которые нужны для тестов. // Ранее созданный mchain передается параметром конструктора // агентов в этих кооперациях. env.introduce_coop( [&]( so_5::coop_t & coop ) { coop.make_agent< a_only_top_level_states_t >( std::ref(log1), notify_ch ); } ); env.introduce_coop( [&]( so_5::coop_t & coop ) { coop.make_agent< a_substates_of_one_state_t >( std::ref(log2), notify_ch ); } ); // Остается просто дождаться двух уведомлений типа complete из нашего mchain-а. receive( from( notify_ch ).handle_n( 2 ), []( complete ){} ); // Уведомления получены. Агенты выполнили свои действия, можно безопасно // завешать работу SObjectizer Environment. env.stop(); } ); |
Комментариев нет:
Отправить комментарий