Timeouts in Ada

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in Ada is possible using tasks and the select statement with delay alternatives.

with Ada.Text_IO;
with Ada.Calendar;
use Ada.Text_IO;
use Ada.Calendar;

procedure Timeouts is
   task type Worker is
      entry Start;
      entry Get_Result(Result : out String);
   end Worker;

   task body Worker is
      Work_Result : String := "result";
   begin
      accept Start;
      delay 2.0;  -- Simulate work that takes 2 seconds
      accept Get_Result(Result : out String) do
         Result := Work_Result;
      end Get_Result;
   end Worker;

   W1, W2 : Worker;
   Result : String(1..10) := (others => ' ');
begin
   -- For our example, suppose we're executing an external
   -- call that returns its result after 2s.
   W1.Start;

   -- Here's the select statement implementing a timeout.
   -- We'll take the timeout case if the operation takes more than the allowed 1s.
   select
      W1.Get_Result(Result);
      Put_Line(Result);
   or
      delay 1.0;
      Put_Line("timeout 1");
   end select;

   -- If we allow a longer timeout of 3s, then we'll get the result.
   W2.Start;
   select
      W2.Get_Result(Result);
      Put_Line(Result);
   or
      delay 3.0;
      Put_Line("timeout 2");
   end select;
end Timeouts;

Running this program shows the first operation timing out and the second succeeding.

$ gnatmake timeouts.adb
$ ./timeouts
timeout 1
result

In this Ada version:

  1. We use tasks instead of goroutines. The Worker task type simulates the work that takes 2 seconds.

  2. The select statement in Ada is used to implement the timeout mechanism. It allows us to wait for either the task to complete or a timeout to occur.

  3. We use delay instead of time.After to implement the timeout.

  4. Ada doesn’t have built-in channels, so we use task entries for communication between the main procedure and the worker tasks.

  5. The structure of the program remains similar, with two operations: one that times out and another that succeeds.

This example demonstrates how to implement timeouts in Ada using tasks and the select statement, providing functionality similar to the original example.