Question

Is there a pattern for a fire and forget mechanism in Ada? When I call a task entry, I don't want the caller to be blocked until the message has been processed. I would like the task to be asynchronous. What I've tried is

loop
    select
        accept xxx(params) do
           -- save the parameters in a queue
        end accept;
        ...
    else
        -- pick the next item off the queue and process it
    end select;
end loop;

It looks like a clumsy mechanism. Maybe fire and forget is the wrong term. I've also tried one task filling up the queue and another taking entries off the queue. Is there a better way of implementing asynchronous tasks in Ada.

Was it helpful?

Solution

If you’re using Ada 2012, the way to go would be to use Ada.Containers.Unbounded_Synchronized_Queues (or the Bounded version): your user code calls Enqueue, your server task calls Dequeue which blocks if the queue is empty.

If not, the normal approach would be to use your own protected object to encapsulate a queue (which is how the Ada 2012 packages do it). Something like

package Parameters is new Ada.Containers.Vectors (Positive, Parameter);
protected Queue is
   procedure Put (P : Parameter);
   entry Get (P : out Parameter);
private
   The_Queue : Parameters.Vector;
end Queue;

protected body Queue is
   procedure Put (P : Parameter) is
   begin
      The_Queue.Append (P);
   end Put;
   entry Get (P : out Parameter) when not The_Queue.Is_Empty is
   begin
      P := The_Queue.First_Element;
      The_Queue.Delete_First;
   end Get;
end Queue;

and then

task body Server is
   P : Parameter;
begin
   loop
      Queue.Get (P);
      --  process P
   end loop;
end Server;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top