El Martes, 26 de Agosto de 2008 17:33, Diego Woitasen escribió:
> On Tue, Aug 26, 2008 at 04:53:59PM -0300, Leandro Lucarella wrote:
> > Herr Groucho, el 26 de agosto a las 16:30 me escribiste:
> > > > No. Para qué querés tener 10001 procesos si con uno alcanza y
> > > > sobre.
> > >
> > > Porque no quiero tener un arreglo de 10000 file descriptors, no
> > > sé si select() o poll() pueden monitorear tal cantidad de file
> > > descriptors (creo que no), y porque estaba bueno escribir el
> > > código del protocolo de comunicación en forma secuencial (te
> > > mando esto, me duerno hasta que contestes. Me fijo que
> > > contestaste, te respondo tal cosa y me duermo de nuevo, etc.)
> > > en lugar de por eventos y estados (en el socket 2182 ya mandé
> > > la preguta, en el 5748 todavía no. Ok, la mando y me acuerdo de
> > > que ya la mandé. Vino un paquete. En qué socket? El 9023. Ah,
> > > en ese ya había mandado la pregunta, e iba por el segundo
> > > intento. Ahora funcionó? Sí, bien. Va la siguiente pregunta y
> > > vuelvo a 0 la cuenta de reintentos y me acuerdo que voy por la
> > > segunda pregunta, etc.).
> >
> > Pensé que no tenías que enviar respuestas, que solamente
> > recolectabas datos, en cuyo caso este modelo es trivial. Si
> > necesitás tener un "protocolo", generalmente lo más conveniente
> > es tener una máquina de estados por cada socket para no perder la
> > cabeza con la secuencialidad (como bien decís).
> >
> > > > No creo que tener threads te beneficie en algo, a menos que
> > > > tengas más de un core, por supuesto.
> > >
> > > Me beneficia en el razopnamiento del problema. Cada
> > > comunicación es independiente y secuencial. Es mentalmente
> > > mucho más simple de modelar la situación con threads que con
> > > eventos. Ver más arriba cómo luce la implementación del
> > > protocolo con threads/procesos independientes y con eventos.
> >
> > Te entiendo, pero si usás máquinas de estado se vuelve reeee
> > manejable.
>
> Yo no estoy tan de acuerdo aca. Salvo que tengas algo muy complejo,
> termina siendo mas facil. Hace un tiempo arme algo similar a lo que
> Groucho plantea con libevent y se muy facil. Es cuestion de cambiar
> un poco la mente  :)

Las máquinas de estado son mi caballito de batalla, no anticipo 
ninguna dificultad por ese lado.
Y tendría que ver cómo es la API de linevent para opinar sobre ella.
Lo que sí me jode de la propuesta de Luca es que tendría que 
reescribir el código del protocolo y de la entidad de comunicación 
que usa el protocolo para obtener datos y hacer algo útil con ellos 
(el master de ahora en más) para que sean reentrantes y su estado 
esté encapsulado y yo pueda pasarle a las rutinas un puntero a una 
estructura conteniendo el estado completo del protocolo y del master, 
eligiendo el estado correcto para el socket correcto. O sea, tendría 
que usar técnicas de programación orientada a objetos, que tampoco me 
son desconocidas, pero el código existente no está hecho así, por lo 
que se trata sólo de más trabajo.

Actualmente la implementación del protocolo siguer esta estructura:
Una serie de funciones xxx_inicializar(), xxx_enviar_pregunta(), 
xxx_obtener_siguiente(), xxx_procesar_respuesta(), 
xxx_limpiar_datos() que conforman el "master de comunicación" (la 
entidad que hace uso de los datos comunicados a través del 
protocolo). Esas funciones son llamadas por un "master genérico", a 
través de unos punteros a función, de modo que en tiempo de ejecución 
puedo reemplazar un master de comunicación por otro que pregunte 
otras cosas, trate de otra manera las respuestas e incluso use otro 
protocolo. Por qué? Porque el protocolo está formado por xxx_init(), 
xxx_fsa() y xxx_tick_1ms() que son otras funciones llamadas a través 
de punteros a función. "xxx" es por supuesto el nombre de un master 
de comunicicación o un protocolo particular. Alterando los punteros, 
puedo reemplazar en tiempo de ejecución un protocolo por otro que 
haga las cosas en forma totalmente diferente. La función xxx_init() 
es llamada cuando el "master genérico" quiere iniciar una 
comunicación. La segunda es llamada "frecuentemente" (ver más abajo) 
para evaluar la máquina de estados del protocolo. La última es 
llamada cada 1 ms si tal facilidad existe. A su vez existen unas 
funciones de bajo nivel no portables que tengo que reescribir cada 
vez que cambio el protocolo de plataforma. Resalto "frecuentemente" 
porque la función xxx_fsa() (la máquina de estados del protocolo) 
puede retornar 3 estados PROTOCOL_PENDING, PROTOCOL_END y 
PROTOCOL_ERROR, que son los valores esperados por el master genérico 
para enterarse de si la última operación solicitada al protocolo está 
pendiente, terminó o se abortó por error. Si implemento las funciones 
de bajo nivel en forma bloqueante, entonces nunca se retorna 
PROTOCOL_PENDING y el master genérico se bloquea hasta tanto ocurra 
algo interesante en el protocolo que es justamente el comportamiento 
ideal. Si hago eso, debo lanzar un hijo para manejar cada 
comuncicación concurrente. Si las funciones de bajo nivel las hago no 
bloqueantes, entonces el xxx_fsa() devolverá PROTOCOL_PENDING cuando 
haya cosas pendientes y el master genérico no transicionará de estado 
ni hará nada. El master genérico en sí es otra máquina de estados 
invocada desde el lazo principal del programa, el cual se puede 
dormir hasta que poll() me diga que ha pasado algo interesante el 
algún socket. Pero todo el estado del protocolo tendría que 
empaquetarlo en una estructura de datos, tener un arreglo de estados 
de protocolo (y del master genérico y del master específico) uno para 
cada comunicación activa, y llamar al master genérico pasándole un 
puntero a ese estado. O sea, estaría haciendo programación orientada 
a objetos casera en C. Ese es el paso de desarrollo que me jode con 
la propuesta de Luca:  hacer reentrante el código del master y del 
protocolo y hacer que todo su estado esté empaquetado en una 
estructura y tener varias de esas estructuras independientes en un 
arreglo para seguir el estado de cada comunicación individual.

Con el enfoque de 1 hijo para cada comunicación, puedo escribir el 
programa como que solo existe una comunicación, porque es lo que cada 
hijo realmente ve.

Al margen, el esquema descripto me permite en el microcontrolador usar 
las mismas funciones de master genérico, master específico y 
protocolo, reescribiendo las rutinas de bajo nivel para que usen en 
lugar de sockets lo que tengo en el runtime del microcontrolador.
Quizás llegó el momento de convertir el protocolo y el master en un 
objeto (en el sentido de la programación orientada a objetos)...

-- 
Herr Groucho

ID Jabber: [EMAIL PROTECTED]
Señal distintiva: LU5MJR - 144,550 MHz FM.
Clave pública GPG: hkp://pks.lugmen.org.ar
Fingerprint GPG: B7BD 0FC7 D9A2 66F3 4EFC  45EE 7DE2 3932 597B 6354

Responder a