Introducción
En Ada, los objetos protegidos son una característica avanzada que permite la sincronización y la comunicación segura entre tareas concurrentes. Los objetos protegidos proporcionan un mecanismo para garantizar que las operaciones críticas se realicen de manera atómica, evitando condiciones de carrera y otros problemas de concurrencia.
Conceptos Clave
- Objeto Protegido: Una estructura que encapsula datos y operaciones, garantizando que las operaciones se realicen de manera segura en un entorno concurrente.
- Operaciones Protegidas: Métodos definidos dentro de un objeto protegido que pueden ser llamados por tareas concurrentes.
- Entrada Protegida: Un tipo especial de operación protegida que puede ser bloqueada hasta que se cumpla una condición específica.
- Exclusión Mutua: Garantiza que solo una tarea puede ejecutar una operación protegida a la vez.
Definición de un Objeto Protegido
Un objeto protegido se define utilizando la palabra clave protected
. Aquí hay un ejemplo básico:
protected type Shared_Counter is procedure Increment; function Value return Integer; private Counter : Integer := 0; end Shared_Counter; protected body Shared_Counter is procedure Increment is begin Counter := Counter + 1; end Increment; function Value return Integer is begin return Counter; end Value; end Shared_Counter;
Explicación del Código
- Declaración del Tipo Protegido:
protected type Shared_Counter is
define un tipo protegido llamadoShared_Counter
. - Operaciones Protegidas:
procedure Increment
yfunction Value return Integer
son las operaciones protegidas que pueden ser llamadas por tareas concurrentes. - Sección Privada:
private
define la sección donde se declaran los datos internos del objeto protegido. En este caso,Counter
es una variable entera que se inicializa a 0. - Cuerpo del Objeto Protegido:
protected body Shared_Counter is
define la implementación de las operaciones protegidas.
Uso de Objetos Protegidos
Para utilizar un objeto protegido, primero se debe declarar una instancia del tipo protegido y luego llamar a sus operaciones:
declare My_Counter : Shared_Counter; begin My_Counter.Increment; Put_Line("Counter Value: " & Integer'Image(My_Counter.Value)); end;
Explicación del Código
- Declaración de la Instancia:
My_Counter : Shared_Counter
declara una instancia del tipo protegidoShared_Counter
. - Llamada a Operaciones Protegidas:
My_Counter.Increment
incrementa el contador yMy_Counter.Value
obtiene el valor actual del contador.
Ejemplo Práctico
Vamos a crear un ejemplo más complejo donde varias tareas incrementan un contador protegido:
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure Main is protected type Shared_Counter is procedure Increment; function Value return Integer; private Counter : Integer := 0; end Shared_Counter; protected body Shared_Counter is procedure Increment is begin Counter := Counter + 1; end Increment; function Value return Integer is begin return Counter; end Value; end Shared_Counter; My_Counter : Shared_Counter; task type Worker is end Worker; task body Worker is begin for I in 1 .. 100 loop My_Counter.Increment; end loop; end Worker; Workers : array (1 .. 10) of Worker; begin delay 1.0; -- Esperar a que todas las tareas terminen Put_Line("Final Counter Value: " & Integer'Image(My_Counter.Value)); end Main;
Explicación del Código
- Declaración del Tipo Protegido: Igual que antes, se define
Shared_Counter
con operacionesIncrement
yValue
. - Declaración de la Instancia:
My_Counter : Shared_Counter
declara una instancia del tipo protegido. - Tarea
Worker
: Se define una tarea que incrementa el contador 100 veces. - Array de Tareas:
Workers : array (1 .. 10) of Worker
declara un array de 10 tareasWorker
. - Sincronización:
delay 1.0
espera un segundo para asegurarse de que todas las tareas hayan terminado antes de imprimir el valor final del contador.
Ejercicio Práctico
Ejercicio
Modifica el ejemplo anterior para que cada tarea Worker
incremente el contador un número aleatorio de veces entre 1 y 100.
Solución
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; with Ada.Numerics.Float_Random; procedure Main is protected type Shared_Counter is procedure Increment; function Value return Integer; private Counter : Integer := 0; end Shared_Counter; protected body Shared_Counter is procedure Increment is begin Counter := Counter + 1; end Increment; function Value return Integer is begin return Counter; end Value; end Shared_Counter; My_Counter : Shared_Counter; task type Worker is end Worker; task body Worker is package Random is new Ada.Numerics.Float_Random; Gen : Random.Generator; Random_Value : Float; Increment_Count : Integer; begin Random_Value := Random.Random(Gen); Increment_Count := Integer(Random_Value * 100.0) + 1; for I in 1 .. Increment_Count loop My_Counter.Increment; end loop; end Worker; Workers : array (1 .. 10) of Worker; begin delay 1.0; -- Esperar a que todas las tareas terminen Put_Line("Final Counter Value: " & Integer'Image(My_Counter.Value)); end Main;
Explicación del Código
- Generación de Números Aleatorios: Se utiliza el paquete
Ada.Numerics.Float_Random
para generar un número aleatorio entre 0 y 1. - Cálculo del Número de Incrementos:
Increment_Count := Integer(Random_Value * 100.0) + 1
convierte el valor aleatorio en un número entero entre 1 y 100. - Bucle de Incremento:
for I in 1 .. Increment_Count loop
incrementa el contador el número aleatorio de veces.
Conclusión
En esta sección, hemos aprendido sobre los objetos protegidos en Ada, cómo definirlos y utilizarlos para sincronizar tareas concurrentes. Los objetos protegidos son una herramienta poderosa para garantizar la seguridad y la integridad de los datos en aplicaciones concurrentes. En la próxima sección, exploraremos los sistemas en tiempo real y cómo Ada maneja la concurrencia en estos entornos.
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