Context in Ada
Here’s the translated code and explanation in Ada, formatted for Hugo:
Our first example demonstrates how to set up a simple HTTP server in Ada. HTTP servers are useful for demonstrating the usage of task cancellation and timeouts. Ada tasks provide a way to handle concurrent operations and can be used to control cancellation and deadlines across different parts of your program.
with Ada.Text_IO;
with Ada.Calendar;
with GNAT.Sockets;
with Ada.Exceptions;
procedure HTTP_Server is
use Ada.Text_IO;
use Ada.Calendar;
use GNAT.Sockets;
task type Request_Handler is
entry Start(Socket : Socket_Type);
end Request_Handler;
task body Request_Handler is
Client_Socket : Socket_Type;
begin
accept Start(Socket : Socket_Type) do
Client_Socket := Socket;
end Start;
Put_Line("server: hello handler started");
declare
Response : constant String :=
"HTTP/1.1 200 OK" & ASCII.CR & ASCII.LF &
"Content-Type: text/plain" & ASCII.CR & ASCII.LF &
"Content-Length: 7" & ASCII.CR & ASCII.LF &
ASCII.CR & ASCII.LF &
"hello" & ASCII.CR & ASCII.LF;
Deadline : constant Time := Clock + Duration(10.0);
begin
select
delay until Deadline;
String'Write(Stream(Client_Socket), Response);
or
terminate;
end select;
exception
when E : others =>
Put_Line("server: " & Ada.Exceptions.Exception_Message(E));
end;
Close_Socket(Client_Socket);
Put_Line("server: hello handler ended");
end Request_Handler;
Server_Socket : Socket_Type;
Server_Address : Sock_Addr_Type;
Client_Address : Sock_Addr_Type;
begin
Initialize;
Create_Socket(Server_Socket);
Server_Address.Addr := Inet_Addr("127.0.0.1");
Server_Address.Port := 8090;
Bind_Socket(Server_Socket, Server_Address);
Listen_Socket(Server_Socket);
Put_Line("Server listening on port 8090");
loop
Accept_Socket(Server_Socket, Client_Address, Client_Socket);
declare
Handler : Request_Handler;
begin
Handler.Start(Client_Socket);
end;
end loop;
exception
when E : others =>
Put_Line("Error: " & Ada.Exceptions.Exception_Message(E));
end HTTP_Server;
In this Ada example, we create a simple HTTP server that listens on port 8090. The Request_Handler
task is responsible for handling each incoming request. It simulates some work by waiting for 10 seconds before sending a response.
The select
statement in the Request_Handler
task body is similar to the select
statement in the original example. It either waits for the 10-second deadline or terminates if the task is asked to complete early.
To run the server:
$ gnatmake http_server.adb
$ ./http_server
Server listening on port 8090
You can then simulate a client request using curl:
$ curl localhost:8090/hello
server: hello handler started
hello
server: hello handler ended
If you interrupt the curl command before the 10-second timeout, you’ll see the handler end early:
$ curl localhost:8090/hello
^C
server: hello handler ended
This example demonstrates how Ada tasks can be used to handle concurrent operations and implement timeouts, similar to the context functionality in the original example.