В выложенной недавно версии 0.3.5 реализован "канонический" вариант работы с таймером (ma::echo::server::session). Данный вариант принципиально отличается от предыдущего (!). В прошлом я намеренно сужал API asio::deadline_timer до Java-вского ScheduledExecutorService, дабы иметь в кармане решение и для Java. Однако, с asio::deadline_timer можно работать эффективнее.
Нужно заметить, что мой варинт отличается от того, что предложил автор Asio:
1. нет таких "подвывертов", как deadline_.expires_at(boost::posix_time::pos_infin);
2. нет явных обращений к now(): deadline_.expires_at() <= deadline_timer::traits_type::now().
3. все обыгрывается за счет двух булевых флагов - их можно было заменить одной переменной с тремя состояниями, но с флагами получилось читабельнее.
P.S. А для ScheduledExecutorService можно сделать все в точности так же и никакого "сужения" не нужно было вовсе 8)
8 комментариев:
пытаясь понять как сейчас работает таймер, обнаружил ошибку копипаста. а заключается ошибка в том, что в методе session::apply_socket_options() переменная-член socket_recv_buffer_size_ используется для задания размера как буфера отправки, так и приема. хотя есть вторая переменная socket_send_buffer_size_.
по поводу таймера - я так и не осилил. не могли бы Вы описать алгоритм типа того, как это сделано в примерах asio. без графиков, конечно.
спасибо 8)
обнаружил ошибку копипаста
Спасибо, исправил.
не могли бы Вы описать алгоритм типа того, как это сделано в примерах asio.
Алгоритм такой же как и в приведенном примере из документации Asio. Почти копия. Отличие состоит в использовании флагов, поясняющих состояние "асинхронного ожидания" и таймера. На основе этих флагов обработчик handle_timer решает был ли он отменен, и, если был отменен, то стоит ли вновь запускать асинхронное ожидание.
ага. понял.
спасибо.
еще раз более углубленно изучил server::session, и признаюсь, это действительно _прямая_ идея и реализация! браво!
спасибо за труд.
действительно _прямая_ идея и реализация
Если Вы про таймер, то это лишь улучшенный пример из документации Asio.
А вот с логикой, состояниями и переходами получилось довольно развесисто из-за необходимости учитывать изменение внутреннего состояния (intern_state_) в каждом handle_*. Но другого пути в общем-то и нет (зато "отзывчато" должно быть). Разве что как-то перенести это на MSM.
я в основном, и в частности о идее использования машины состояний. это здорово!
о идее использования машины состояний
Обратите внимание: используются несколько КА:
1. extern_state_ - внешний КА, определяющий допустимые воздействия извне;
2. intern_state_ - основной внутренний КА, так сказать, lifecycle of session;
3. read_state_ - чтение из сокета;
4. write_state_ - запись в сокет;
5. timer_state_ - ожидание на таймере + дополнительно используются вложенные состояния определяемые флагами timer_wait_cancelled_ и timer_turned_.
Можно назвать это единым КА, состояние которого описывается вектором из вышеперечисленных компонент. Но разложить на несколько взаимодействующих КА все же оказалось проще.
Что-то не нашел литературы по таким вопросам. Было что-то по коммуникационному оборудованию, но слишком далекое и сложное.
Самое сложное - взаимодействие между КА. Трудно не попасть в цикл и трудно сделать код простым/коротким.
Надо добавить, что в примерах Asio все внутренние флаги по сути являются зачатками КА.
Что-то не нашел литературы по таким вопросам. Было что-то по коммуникационному оборудованию, но слишком далекое и сложное.
Вот "оно". Буду читать на досуге "до просветления".
Заодно вот еще интересная статья.
Отправить комментарий