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
