То, о чем мне так долго говорили большевики все вокруг, нашло таки свое воплощение в жизни :) В SObjectizer появилось синхронное взаимодействие между агентами. Реализовано оно на основе C++11 классов std::promise и std::future. Что дает возможность делать не просто синхронное взаимодействие, но и более хитрые варианты.
Пока это всего лишь черновой вариант, который был опробован всего на одном компиляторе, и над которым еще предстоит работать напильником. Но начало уже положено, что не может не радовать.
Полный пример использования синхронного взаимодействия можно увидеть здесь. А вот небольшая выжимка:
Ключевые фрагменты агента, который предоставляет синхронный сервис:
virtual void so_define_agent() { so_subscribe( m_self_mbox ) .service( &a_convert_service_t::svc_convert ); } std::string svc_convert( const so_5::rt::event_data_t< msg_convert > & evt ) { std::cout << "svc_convert called: value=" << evt->m_value << std::endl; std::ostringstream s; s << evt->m_value; return s.str(); } |
Ключевые фрагменты агента, который обращается к синхронным сервисам других агентов. Параметры для синхронного сервиса все равно нужно передавать в виде динамически созданного объекта, т.к. их доставка осуществляется через очередь сообщений обычным для SObjectizer-а способом.
virtual void so_evt_start() { auto hello = //NOTE: it could be a method of agent_t. so_5::rt::service< std::string >( m_svc_mbox ) .request< msg_hello_svc >(); auto convert = so_5::rt::service< std::string >( m_svc_mbox ) .request( new msg_convert( 42 ) ); std::cout << "hello_svc: " << hello.get() << std::endl; std::cout << "convert_svc: " << convert.get() << std::endl; std::cout << "sync_convert_svc: " << so_5::rt::service< std::string >( m_svc_mbox ) .sync_request( new msg_convert( 1020 ) ) << std::endl; // More complex case with conversion. auto svc_proxy = so_5::rt::service< std::string >( m_svc_mbox ); // These requests should be processed before next 'sync_request'... auto c1 = svc_proxy.request( new msg_convert( 1 ) ); auto c2 = svc_proxy.request( new msg_convert( 2 ) ); // Two previous request should be processed before that call. std::cout << "sync_convert_svc: " << svc_proxy.sync_request( new msg_convert( 3 ) ) << std::endl; // But their value will be accessed only now. std::cout << "convert_svc: c2=" << c2.get() << std::endl; std::cout << "convert_svc: c1=" << c1.get() << std::endl; so_environment().stop(); } |
Пока выглядит многословно. Но, думаю, если тщательно разобраться с С++11 variadic templates и std::forward, объем писанины можно будет посократить.
Комментариев нет:
Отправить комментарий