RoboSim

Conceptos Básicos de
Programación
Robosim
Tecnologías en Robosim
 Comunicaciones TCP-IP
• Necesitamos utilizar cadenas alfanuméricas y
las librerías de comunicaciones.
 Programación distribuida
• Necesitamos utilizar objetos de sincronismo y
librerías para la gestión de threads.
 Inteligencia Artificial
• Necesitamos utilizar estructuras de datos y
variables dinámicas.
Robosim
Razones para Multi-hilo
 Desarrollar un programa multi-hilo (multi-
thread) es más complicado que uno
monohilo, así pues ¿Por qué es necesario?
 Respuesta 1: La función recv (o read)
detiene la ejecución del programa hasta que
se recibe la información.
 Respuesta 2: Si la información recibida por el
socket no se procesa (se ejecuta
inmediatamente recv ó read), esta
información se acumula => Necesitamos 1
hilo escuchando el puerto permanentemente.
Robosim
¿Qué es multitarea?
 “Una ilusión”. La mayor parte de los
ordenadores son monotarea.
 La multitarea consiste en repartir el
tiempo de ejecución entre los procesos e
hilos que se estén ejecutando, de forma
que, aparentemente, se ejecutan todos a
la vez.
 Existen programas llamados “scheduler ”
que se encargan de repartir el tiempo de
ejecución (en slots de ejecución dedicados
a un hilo o proceso). Un scheduler es un
gestor de procesos e hilos.
Robosim
Pero ¿Qué es un hilo?
 Consideremos un programa para línea de
comandos en C, ese programa tiene un “punto de
invocación”: la función main y es monotarea
porque se ejecutan cada sentencia de ese main
secuencialmente. Sólo se empieza una sentencia
cuando ha acabado la anterior.
 Diseñemos una tarea específica e implementemos
una función con ella. Invoquemos a esa función,
pero dejemos que esa función se ejecute como si
fuese un programa “aparte” y por tanto que el
main siga su propia ejecución si espera a la
finalización de la función. Ya tengo un hilo (un
thread).
Robosim
Arrancar un hilo
 Para arrancar un hilo es necesario:
• Una función con las sentencias del hilo.
• Una forma de invocar la función que no sea
una simple llamada. Es decir, usar el gestor de
hilos.
 En Windows:
• CreateThread (está en la API de Windows)
• Con parámetros “importantes”:
 El “punto de invocación” (es decir, la función)
 Un parámetro opcional para esa función.
 Otros parámetros: prioridad, tamaño de stack, …
Robosim
Compartir Datos entre Hilos
 Normalmente los hilos deben compartir
información.
 Los procesos de acceso y escritura de variables
(especialmente cuando son compuestas) puede
llegar a repartirse entre slots de ejecución.
 Si esto ocurre y 2 hilos entran a acceder o
modificar la misma variable se producen errores.
 Por tanto, es necesario gestionar el acceso y
modificación de datos compartidos entre hilos =>
sincronización de hilos.
 Terminología: Recursos  Variables, datos,
archivos...
Robosim
Sincronización de Hilos
 Idea fundamental: Semáforo.
• Impedir el acceso a un “recurso” de 2 hilos a la vez.
• Cuando un hilo accede al recurso “bloquea” el acceso del
resto de recursos.
• Ver “sincronización de hilos”
 Implementación:
• Antes del código de acceso-modificación se hace una
petición de bloqueo-espera.
• Si se concede se pasa a ejecutar el código y se bloquea
el semáforo para el resto de hilos.
• Si no se concede el hilo se bloquea (se detiene su
ejecución) hasta que se libere el semáforo.
• Tarde o temprano se liberará el semáforo y se ejecuta el
código “conflictivo”.
• Cuando se acaba el código se debe liberar el semáforo.
Robosim
¿Dónde se colocan?
 En primer lugar es necesario conocer (o diseñar) con
claridad los “recursos” (es decir, las variables, datos
o archivos) compartidos entre hilos.
 Si el recurso está preparado no es necesario hacer
nada (no es el caso corriente, pero existen). Se
suelen decir que son implementaciones multithread.
 En caso contrario, se debe:
• Declarar y compartir entre hilos un objeto de sincronismo
(un semáforo).
• Siempre que se acceda (se use el valor del recurso) o se
modifique en cualquier hilo se debe colocar el semáforo (la
petición-bloqueo-espera y la liberación-desbloqueo).
Robosim
Objetos de Sincronismo
 En Windows:
• Mutex (RS_Server utiliza estos)
• Critical Sections
• Events (RS_Server también utiliza estos)
• …
 En otros sistemas:
• Nombres parecidos, pero cuidado, el mismo
nombre de objeto de sincronismo puede
representar distinto tipo de “semáforo” en otro
sistema o librería.
Robosim
Bloqueo y Liberación
 La petición de bloqueo y la liberación
se hacen a través de funciones (o
métodos, interfaces, …) que tienen
como parámetros el objeto de
sincronismo.
 Por ejemplo:
• WaitForSingleObject (espera y bloquea
un objeto de sincronismo)
• ReleaseMutex (libera un objeto de
sincronismo tipo mutex)
Robosim
Compartir memoria entre hilos
 No siempre se pueden compartir datos en
memoria entre hilos o procesos (hay que
consultar la documentación del sistema).
 Generalmente la memoria se comparte en
la zona de heap (variables dinámicas,
suele ser común para todos los hilos de un
proceso), las zonas de stack (variables
locales de las funciones) de los hilos
suelen estar separadas.
Robosim
Sincronización vía
Pila de Mensajes
 Cuando la comunicación entre hilos es muy
frecuente es muy útil utilizar una “pila de
mensajes” (mala tradución de message queuing
en realidad es una cola).
 La idea consiste en enviar información (un
mensaje) a otro hilo de forma asíncrona (es
decir, en cualquier momento y sólo
opcionalmente esperando una respuesta).
 El hilo que recibe almacena los mensajes en una
estructura tipo “cola” o FIFO.
 Procesa los mensajes sacándolos de la fifo en un
bucle infinito que no hace nada si no hay
mensajes pendientes de resolver.
Robosim
Implementación de
la pila de mensajes
 Se necesita:
• Una estructura tipo lista común a todos los hilos con una
operación de inserción al final y otra de extracción del
primer elemento y preparada para multihilo mediante
semáforos.
• Un bucle infinito que compruebe si la lista está vacía y si
no lo está quite el primer elemento y lo procese.
 Alternativamente podemos usar el message
queuing de Windows (esta es la opción que se usa
para comunicar RS_Server y RS_Visual y algunos
hilos dentro de RS_Server).
 Útil si utilizáis distintos tipos de control a largo y
corto plazo para comunicar sus algoritmos.
Robosim
Otra técnica para mejorar la
sincronización
 Compare-and-swap
• Aunque la implementación de esta técnica es
bastante compleja podemos usar la idea
subyacente para mejorar el inter-bloqueo de
nuestros algoritmos.
• Podemos:
 Usar varios “recursos” de un mismo tipo (quizás
tantos o más como hilos), los apuntamos con
distintos punteros. Lo normal es que el recurso sea
una estructura de datos, por ejemplo, una lista.
 Cada hilo actúa sobre un puntero distinto y cuando
acaba intercambiamos los punteros.
Robosim
¿Y que hago con mis hilos?
 Los hilos los introducimos si queremos
realizar tareas concurrentes (a la vez) y
no queremos ocuparnos de distribuir el
tiempo de ejecución nosotros mismos
(cosa complicada por otro lado).
 Cada hilo debería realizar una tarea
distinta.
 Muchos hilos pueden funcionar en bucles
infinitos. Simplemente hay que asegurarse
que el schuduler es capaz de suspender la
ejecución de ese hilo y pasar al siguiente
(en ocasiones hace falta poner un sleep).