Thread: Re: [Asio-samples-users] добавление API записи чтения в echo_server
Status: Beta
Brought to you by:
mabrarov
From: Marat A. <ab...@gm...> - 2012-05-07 09:07:58
|
Добрый день. > подскажите, каким образом, наиболее эффективно, можно изменить session > так, чтоб добавить методы чтения/записи для использования в > пользовательской логике? В том-то и дело, что решение о "старте" чтения/записи принимает КА, а не пользовательская логика. Т.е. правильнее сказать так: есть КА для процесса чтения и есть КА для процесса записи. Оба эти автомата кроме собственного состояния учитывают еще и наличие места в буфере (он сделан общим, но это только для ограничения объема и эффективного использования), т.е. доп. состояния/флаги. Пользовательская логика должна взаимодействовать с этими КА, но не с сокетом (lower layer по отношению к КА) напрямую. В простейшем случае такое взаимодействие (или правильнее "воздействие") можно выразить через изменение состояния буферов ввода/вывода (и прочих состояний других КА) и вызов session::continue_work() (скорее всего, это место тоже придется модифицировать). Я не уверен, что КА (их несколько и они связаны) в echo_server организованы достаточно понятно и просто (для дальнейших модификаций). Оптимально - да, возможно. Но отсечение многих частей делает неясным и неявным некоторые аспекты взаимодействия этих КА. В связи с этим, я пытаюсь изобразить (UML state machine) эти КА и связать их взаимодействие общими событиями (это та часть документации, без которой уже сложно двигаться дальше). По-моему, именно набор взаимосвязанных КА наиболее обобщенно описывает real life (например, клетки и процессы в них) и communicating software (где все есть множество взаимосвязанных параллельных/fork-ющихся процессов). Ну, об этом я уже писал: http://asio-samples.blogspot.com/2009/10/httpwww.html. Regards, Marat Abrarov. |
From: Marat A. <ab...@gm...> - 2012-05-07 10:15:06
|
> 1. с чего начать С session::continue_work(). > 2. что изменять Вводить новые состояния/флаги/КА (через тот же user_context) и учитывать их в session::continue_work(). > 3. на что обратить внимание На то, что есть несколько КА: 1. Общий внешний КА, наблюдаемый извне класса session. Он, по сути, повторяет следующий, но с запозданием. 2. Внутренний общий КА а-ла session's lifecycle. 3. (Внутренний) КА для таймера. 4. (Внутренний) КА для отправки данных через сокет. 5. (Внутренний) КА для приема данных из сокета. Все КА влияют друг на друга своими событиями. Например, "Внутренний общий КА" не перейдет в состояние intern_state::stopped, пока есть pending_operations_, т.е. пока все остальные "внутренние КА" не перейдут в состояние stopped. > 4. какая последовательность вызовов+логика > etc... > > не могли бы Вы выразить это в псевдокоде+словах, пожалуйста. Как я писал ранее - надо переварить (нужно время). После того, как нарисую диаграммы для КА (UML state machine), Ваши вопросы, полагаю, отпадут сами собой. Вообще будет здорово, если удастся перевести на Boost.MSM.... хотя бы для примера. Regards, Marat Abrarov. |
From: niXman <i.n...@gm...> - 2012-05-07 13:08:27
|
7 мая 2012 г. 14:14 пользователь Marat Abrarov написал: > Вводить новые состояния/флаги/КА (через тот же user_context) и учитывать их в session::continue_work(). давайте попробуем на конкретном примере... к примеру, я хочу добавить api чтения: void user_read(???); вопросы: 1. аргументом указывать только размер? или размер и буфер в который читать? (callback - само собой) 2. насколько я понимаю, user_read() не создает нового состояния КА, он просто должен устанавливать session::read_state в in_progress ? 3. с записью - так же, user_write() не создает нового состояния КА, он должен устанавливать session::write_state в in_progress ? тут я все правильно понял? спасибо. -- Regards, niXman |
From: niXman <i.n...@gm...> - 2012-05-08 10:55:33
|
7 мая 2012 г. 14:14 пользователь Marat Abrarov написал: > На то, что есть несколько КА: > 1. Общий внешний КА, наблюдаемый извне класса session. Он, по сути, повторяет следующий, но с запозданием. > 2. Внутренний общий КА а-ла session's lifecycle. > 3. (Внутренний) КА для таймера. > 4. (Внутренний) КА для отправки данных через сокет. > 5. (Внутренний) КА для приема данных из сокета. > > Все КА влияют друг на друга своими событиями. Например, "Внутренний общий КА" не перейдет в состояние intern_state::stopped, пока есть pending_operations_, т.е. пока все остальные "внутренние КА" не перейдут в состояние stopped. жуть какая %) попытался представить состояние этих КА в конкретные моменты времени, и, честно говоря, моцг плавится... -- Regards, niXman |
From: niXman <i.n...@gm...> - 2012-05-08 12:11:43
|
в общем, мне чтоб продолжить работать в обозначенном направлении, нужно понять как реализовать api чтения/записи. и без Вашей помощи(как я уже убедился), у меня вряд ли получится. спасибо ;) -- Regards, niXman |
From: Marat A. <ab...@gm...> - 2012-05-07 15:38:08
|
> давайте попробуем на конкретном примере... > к примеру, я хочу добавить api чтения: void user_read(???); > вопросы: > 1. аргументом указывать только размер? или размер и буфер в который > читать? (callback - само собой) Это "API" наподобие session::async_start/async_wait/async_stop или что-то внутреннее для расширения session? Для внутренних частей неплохо бы обойтись без callback-ов - они добавляют сложности коду и overhead для runtime. > 2. насколько я понимаю, user_read() не создает нового состояния КА, он > просто должен устанавливать session::read_state в in_progress ? Не создает - да. Но session::read_state_ в in_progress устанавливает только (!) start_socket_read. Скорее user_read должен проверять read_state_ и, если read_state_ == read_state::wait, вызывать start_socket_read. > 3. с записью - так же, user_write() не создает нового состояния КА, он > должен устанавливать session::write_state в in_progress ? Здесь аналогично. Остается неясным, кто и когда будет вызывать user_read/user_write. Regards, Marat Abrarov. |
From: niXman <i.n...@gm...> - 2012-05-07 15:50:55
|
> Это "API" наподобие session::async_start/async_wait/async_stop или что-то внутреннее для расширения session? > Для внутренних частей неплохо бы обойтись без callback-ов - они добавляют сложности коду и overhead для runtime. "это" предполагается предоставить реализатору user_context`ов. т.е. как-то так: struct base_context { void read(...) {} void write(...) {} bool in_read() const; bool in_write() const; ... }; struct user_context: base_context { user_context(...) :base_context(...) { start(); } void start() { read(..., &user_context::readed, ...); } void readed(...) { // тут юзер что-то выполняет, и вызывет write(), или read() если пакет составной } }; > Не создает - да. Но session::read_state_ в in_progress устанавливает только (!) start_socket_read. > Скорее user_read должен проверять read_state_ и, если read_state_ == read_state::wait, вызывать start_socket_read. понял. > Остается неясным, кто и когда будет вызывать user_read/user_write. реализатор user_context`ов. или имеются какие-то соображения/предложения? и по поводу буферов для пользовательских данных, есть мысли? у меня, собственно говоря, есть мысль оставить буфер(а) членами session, но при помощи base_context предоставить пользователю возможность управлять/использовать/настраивать его/их. как Вы думаете? -- Regards, niXman |
From: niXman <i.n...@gm...> - 2012-05-07 16:40:18
|
т.е. в конечном счете, я полагаю, должно получиться нечто вроде: template<typename SD> // session data struct base_context { base_context(SD& sd) :_data(sd) {} void read(...) { _data... } void write(...) { _data... } cyclic_buffer& buffer() const { return _data... } bool in_read() const { return _data... } bool in_write() const { return _data... } private: SD& _data }; /* * тут SD введен для того, что не раскрывать детали сервера. */ /***************************************************************************/ template< typename GC ,typename SD > struct user_context: base_context<SD> { user_context(GC& gc, SD& sd) :base_context<SD>(sd) { // к моменту вызова тела конструктора user_context`а, все члены и данные // session и base_context`а инициализированы. // таким образом, пользовательская логика берет начало в конструкторе, где // пользователь может вызывать read() или write(). // можно, кстати, в base_context добавить виртуальный метод start(), вызываемый сессией, // переопределив который пользователь может запускать свою логику в нем. // так же, можно добавить и метод stop(), который быдет вызываться сессией // в самом начале разрушения сессии. } }; /***************************************************************************/ http://liveworkspace.org/code/30bd677be00ff717657e52a66146bf19 интересует Ваше мнение об этом. благодарю. -- Regards, niXman |
From: Marat A. <ab...@gm...> - 2012-05-08 18:26:59
|
> жуть какая %) > попытался представить состояние этих КА в конкретные моменты времени, > и, честно говоря, моцг плавится... Вот для этого и нужны диаграммы. Мозгу будет легче, если он начнет с того, что в контексте одного экземпляра session может одновременно работать несколько параллельных (и местами синхронизированных) процессов, каждый из которых (для простоты) представлен в виде КА 8) Конкретный экземпляр session для таких параллельных процессов есть shared data. Остальное в течение недели. Regards, Marat Abrarov. |
From: niXman <i.n...@gm...> - 2012-05-09 11:59:23
|
8 мая 2012 г., 22:26 пользователь Marat Abrarov написал: > Остальное в течение недели. ок. ожидаю. -- Regards, niXman |
From: niXman <i.n...@gm...> - 2012-05-07 09:19:58
|
7 мая 2012 г. 13:07 пользователь Marat Abrarov написал: > Добрый день. > >> подскажите, каким образом, наиболее эффективно, можно изменить session >> так, чтоб добавить методы чтения/записи для использования в >> пользовательской логике? > > В том-то и дело, что решение о "старте" чтения/записи принимает КА, а не пользовательская логика. > > Т.е. правильнее сказать так: есть КА для процесса чтения и есть КА для процесса записи. Оба эти автомата кроме собственного состояния учитывают еще и наличие места в буфере (он сделан общим, но это только для ограничения объема и эффективного использования), т.е. доп. состояния/флаги. > > Пользовательская логика должна взаимодействовать с этими КА, но не с сокетом (lower layer по отношению к КА) напрямую. В простейшем случае такое взаимодействие (или правильнее "воздействие") можно выразить через изменение состояния буферов ввода/вывода (и прочих состояний других КА) и вызов session::continue_work() (скорее всего, это место тоже придется модифицировать). > > Я не уверен, что КА (их несколько и они связаны) в echo_server организованы достаточно понятно и просто (для дальнейших модификаций). Оптимально - да, возможно. Но отсечение многих частей делает неясным и неявным некоторые аспекты взаимодействия этих КА. В связи с этим, я пытаюсь изобразить (UML state machine) эти КА и связать их взаимодействие общими событиями (это та часть документации, без которой уже сложно двигаться дальше). По-моему, именно набор взаимосвязанных КА наиболее обобщенно описывает real life (например, клетки и процессы в них) и communicating software (где все есть множество взаимосвязанных параллельных/fork-ющихся процессов). Ну, об этом я уже писал: http://asio-samples.blogspot.com/2009/10/httpwww.html. спасибо за ответ! но из всего вышеописанного, я так и не понял следующее: 1. с чего начать 2. что изменять 3. на что обратить внимание 4. какая последовательность вызовов+логика etc... не могли бы Вы выразить это в псевдокоде+словах, пожалуйста. спасибо. -- Regards, niXman |