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 Workerdefine una tarea con una entradaStart_Work. - Implementación de la Tarea:
task body Workerimplementa la tarea y define el comportamiento durante el rendezvous. - Tarea Principal:
task body Maincrea una instancia de la tareaWorkery llama aStart_Workpara 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_Counterdefine un objeto protegido con un procedimientoIncrementy una funciónGet_Value. - Implementación del Objeto Protegido:
protected body Shared_Counterimplementa el procedimiento y la función. - Tarea Principal:
task body Maincrea 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 Bufferdefine un buffer con entradasAdd_ItemyGet_Item. - Implementación del Objeto Protegido:
protected body Bufferimplementa las entradas y controla el estado del buffer. - Tarea Productor:
task type Producery su implementación generan datos y los añaden al buffer. - Tarea Consumidor:
task type Consumery su implementación obtienen datos del buffer y los procesan. - Tarea Principal:
task body Maincrea instancias de las tareasProduceryConsumer, 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
