En este tema, exploraremos cómo Ada maneja la sincronización y la comunicación entre tareas. Ada proporciona mecanismos robustos para la concurrencia, lo que permite a los programadores escribir aplicaciones concurrentes y en tiempo real de manera segura y eficiente.
Conceptos Clave
- Tareas: Unidades de ejecución concurrente en Ada.
- Rendezvous: Mecanismo de sincronización y comunicación entre tareas.
- Entradas y Salidas de Tareas: Métodos para definir puntos de comunicación en tareas.
- Objetos Protegidos: Estructuras que permiten la sincronización y la comunicación segura entre tareas.
Rendezvous
El rendezvous es un mecanismo fundamental en Ada para la sincronización y la comunicación entre tareas. Permite que una tarea espere a que otra tarea llegue a un punto específico de ejecución antes de continuar.
Ejemplo de Rendezvous
-- Declaración de la tarea task type Worker is entry Start_Work; end Worker; -- Implementación de la tarea task body Worker is begin accept Start_Work do -- Código que se ejecuta durante el rendezvous Put_Line("Worker is starting work."); end Start_Work; end Worker; -- Declaración de la tarea principal task body Main is W : Worker; begin -- Iniciar el rendezvous W.Start_Work; end Main;
Explicación del Código
- Declaración de la Tarea:
task type Worker
define una tarea con una entradaStart_Work
. - Implementación de la Tarea:
task body Worker
implementa la tarea y define el comportamiento durante el rendezvous. - Tarea Principal:
task body Main
crea una instancia de la tareaWorker
y llama aStart_Work
para iniciar el rendezvous.
Objetos Protegidos
Los objetos protegidos en Ada proporcionan una forma segura de sincronización y comunicación entre tareas. Permiten el acceso controlado a los datos compartidos y garantizan la exclusión mutua.
Ejemplo de Objeto Protegido
-- Declaración del objeto protegido protected type Shared_Counter is procedure Increment; function Get_Value return Integer; private Counter : Integer := 0; end Shared_Counter; -- Implementación del objeto protegido protected body Shared_Counter is procedure Increment is begin Counter := Counter + 1; end Increment; function Get_Value return Integer is begin return Counter; end Get_Value; end Shared_Counter; -- Declaración de la tarea principal task body Main is Counter : Shared_Counter; begin -- Incrementar el contador Counter.Increment; -- Obtener el valor del contador Put_Line("Counter value: " & Integer'Image(Counter.Get_Value)); end Main;
Explicación del Código
- Declaración del Objeto Protegido:
protected type Shared_Counter
define un objeto protegido con un procedimientoIncrement
y una funciónGet_Value
. - Implementación del Objeto Protegido:
protected body Shared_Counter
implementa el procedimiento y la función. - Tarea Principal:
task body Main
crea una instancia del objeto protegidoShared_Counter
, incrementa el contador y obtiene su valor.
Ejercicio Práctico
Ejercicio
Crea un programa en Ada que utilice tareas y objetos protegidos para simular un sistema de productores y consumidores. Los productores deben generar datos y los consumidores deben procesarlos. Utiliza un objeto protegido para almacenar los datos generados y garantizar la sincronización entre productores y consumidores.
Solución
-- Declaración del objeto protegido protected type Buffer is entry Add_Item(Item : Integer); entry Get_Item(Item : out Integer); private Data : Integer := 0; Full : Boolean := False; end Buffer; -- Implementación del objeto protegido protected body Buffer is entry Add_Item(Item : Integer) when not Full is begin Data := Item; Full := True; end Add_Item; entry Get_Item(Item : out Integer) when Full is begin Item := Data; Full := False; end Get_Item; end Buffer; -- Declaración de la tarea Productor task type Producer(Buffer : access Buffer) is end Producer; -- Implementación de la tarea Productor task body Producer is begin for I in 1 .. 10 loop Buffer.Add_Item(I); Put_Line("Produced: " & Integer'Image(I)); end loop; end Producer; -- Declaración de la tarea Consumidor task type Consumer(Buffer : access Buffer) is end Consumer; -- Implementación de la tarea Consumidor task body Consumer is Item : Integer; begin for I in 1 .. 10 loop Buffer.Get_Item(Item); Put_Line("Consumed: " & Integer'Image(Item)); end loop; end Consumer; -- Declaración de la tarea principal task body Main is Shared_Buffer : aliased Buffer; P : Producer(Shared_Buffer'Access); C : Consumer(Shared_Buffer'Access); begin null; end Main;
Explicación del Código
- Declaración del Objeto Protegido:
protected type Buffer
define un buffer con entradasAdd_Item
yGet_Item
. - Implementación del Objeto Protegido:
protected body Buffer
implementa las entradas y controla el estado del buffer. - Tarea Productor:
task type Producer
y su implementación generan datos y los añaden al buffer. - Tarea Consumidor:
task type Consumer
y su implementación obtienen datos del buffer y los procesan. - Tarea Principal:
task body Main
crea instancias de las tareasProducer
yConsumer
, y un buffer compartido.
Conclusión
En esta sección, hemos aprendido sobre los mecanismos de sincronización y comunicación en Ada, incluyendo el rendezvous y los objetos protegidos. Estos conceptos son fundamentales para escribir aplicaciones concurrentes y en tiempo real de manera segura y eficiente. En el próximo módulo, exploraremos temas avanzados como el manejo de excepciones y la entrada/salida en Ada.
Curso de Programación en Ada
Módulo 1: Introducción a Ada
Módulo 2: Conceptos Básicos
- Variables y Tipos de Datos
- Operadores y Expresiones
- Estructuras de Control
- Bucles en Ada
- Subprogramas: Procedimientos y Funciones
Módulo 3: Tipos de Datos Avanzados
Módulo 4: Programación Modular
Módulo 5: Concurrencia y Programación en Tiempo Real
Módulo 6: Temas Avanzados
Módulo 7: Mejores Prácticas y Optimización
- Estilo de Código y Mejores Prácticas
- Depuración y Pruebas
- Optimización del Rendimiento
- Consideraciones de Seguridad