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

  1. Tareas: Unidades de ejecución concurrente en Ada.
  2. Rendezvous: Mecanismo de sincronización y comunicación entre tareas.
  3. Entradas y Salidas de Tareas: Métodos para definir puntos de comunicación en tareas.
  4. 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

  1. Declaración de la Tarea: task type Worker define una tarea con una entrada Start_Work.
  2. Implementación de la Tarea: task body Worker implementa la tarea y define el comportamiento durante el rendezvous.
  3. Tarea Principal: task body Main crea una instancia de la tarea Worker y llama a Start_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

  1. Declaración del Objeto Protegido: protected type Shared_Counter define un objeto protegido con un procedimiento Increment y una función Get_Value.
  2. Implementación del Objeto Protegido: protected body Shared_Counter implementa el procedimiento y la función.
  3. Tarea Principal: task body Main crea una instancia del objeto protegido Shared_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

  1. Declaración del Objeto Protegido: protected type Buffer define un buffer con entradas Add_Item y Get_Item.
  2. Implementación del Objeto Protegido: protected body Buffer implementa las entradas y controla el estado del buffer.
  3. Tarea Productor: task type Producer y su implementación generan datos y los añaden al buffer.
  4. Tarea Consumidor: task type Consumer y su implementación obtienen datos del buffer y los procesan.
  5. Tarea Principal: task body Main crea instancias de las tareas Producer y Consumer, 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.

© Copyright 2024. Todos los derechos reservados