Я думаю о написании пользовательской службы Asio поверх существующего проприетарного сетевого протокола сторонних разработчиков, который мы сейчас используем.
В соответствии с Highscore Asio guide вам нужно реализовать три класса для создания пользовательской службы Asio:
- Класс, полученный из
boost::asio::basic_io_object
, представляющий новый объект ввода-вывода. - Класс, полученный из
boost::asio::io_service::service
, представляющий сервис, который зарегистрирован в службе ввода-вывода, и к нему можно получить доступ из объекта ввода-вывода. - Класс, не полученный из любого другого класса, представляющего реализацию службы.
Реализация сетевого протокола уже предоставляет асинхронные операции и имеет (блокирующий) цикл событий. Поэтому я подумал, что я поместил бы его в класс реализации службы и запустил цикл событий во внутреннем потоке рабочего. Пока все хорошо.
Посмотрев на некоторые примеры пользовательских сервисов, я заметил, что классы обслуживания порождают собственные внутренние потоки (фактически они создают собственные внутренние экземпляры io_service). Например:
-
Страница Highscore предоставляет пример монитора каталога. Это, по сути, обертка вокруг inotify. Интересными классами являются
inotify/basic_dir_monitor_service.hpp
иinotify/dir_monitor_impl.hpp
.Dir_monitor_impl
обрабатывает фактическое взаимодействие с inofity, которое блокирует и, следовательно, работает в фоновом потоке. Я согласен с этим. Ноbasic_dir_monitor_service
также имеет внутренний рабочий поток, и все, что, кажется, делает, это перетасовывать запросы между основнымиio_service
иDir_monitor_impl
. Я играл с кодом, удалял рабочий поток вbasic_dir_monitor_service
и вместо этого отправлял запросы непосредственно в основной io_service, и программа по-прежнему выполнялась по-прежнему. -
В Asio пользовательский пример службы журналов я заметил тот же подход.
logger_service
порождает внутренний рабочий поток для обработки запросов на ведение журнала. У меня не было времени, чтобы поиграть с этим кодом, но я думаю, что можно отправлять эти запросы непосредственно в основной io_service.
В чем преимущество наличия этих "посреднических работников"? Разве вы не могли постоянно публиковать всю работу в основном io_service? Пропустил ли я какой-то важный аспект шаблона Proactor?
Возможно, я должен упомянуть, что я пишу программное обеспечение для маломощной встроенной системы. Наличие этих дополнительных потоков на месте просто, кажется, навязывает ненужные переключатели контекста, которые я хотел бы избежать, если это возможно.