1

让我先用代码说明这个问题:

with Ada.Text_IO;

procedure Test
is

   task type Serving_Task is
      entry Start;
   end Serving_Task;

   task body Serving_Task is begin
      accept Start;
      Ada.Text_IO.Put_Line ("Started");
      loop
         null; --  Blocking operation, eg. accepting on a socket.
         null; --  Processing on blocking operation's result.
      end loop;
      Ada.Text_IO.Put_Line ("Stopped");
   end Serving_Task;

   type Server is tagged limited record
      Serving : Serving_Task;
   end record;

   procedure Start
     (S : in out Server)
   is begin
      Ada.Text_IO.Put_Line ("Starting");
      S.Serving.Start;
   end Start;

   procedure Stop
     (S : in out Server)
   is begin
      Ada.Text_IO.Put_Line ("Stopping");
      -- TODO To implement.
   end Stop;

   Main_Server : Server;

begin
   Ada.Text_IO.Put_Line ("Calling Start");
   Start (Main_Server);
   delay 5.0;
   Ada.Text_IO.Put_Line ("Calling Stop");
   Stop (Main_Server);
end Test;

这是典型的服务器构造 - 有一个服务器任务带有一个循环接受传入连接。我的问题是 - 实现类型Stop程序的最佳方法是什么Server

我希望它等到服务任务阻塞接受套接字(或在阻塞调用之前,所以如果在终止任务之前完全处理每个接受的请求)并退出循环,因此任务可以在终止之前清理。

首先想到的是添加

select
   accept Stop;
or
   delay 0.1;
   exit;
end select;

在循环结束时,但每次迭代浪费了 0.1 秒。似乎意义重大。

我在 RM、Lovelace 教程和 Wikibook 中查看了一些示例,但似乎没有什么合适的。

在 Ada 中,此类(我相信相当普遍)问题的最佳实践是什么?

而答案是……

基于Marc C答案的示例解决方案:https ://gist.github.com/3413017

4

2 回答 2

2

你想要其他版本:

loop
   -- blocking read from socket
   -- process the data received
   select
      accept Stop;
      exit;
   else
      null;
   end select;
end loop;
于 2012-08-20T11:31:09.513 回答
1

我通常设置的方法是首先使用 AdaCore 的 GNAT.Sockets 包,而不是直接对套接字进行编程。由于我将使用 (socket) select() 函数(包装为 Check_Selector)在套接字上有可用数据时收到通知,因此 GNAT.Sockets 提供了一个可以从其他地方调用的 Abort_Selector() 过程。由于 Check_Selector() 上的任务被阻止,我只是等待数据到达(状态 = 已完成)或该退出的标志(状态 = 中止)。

请参阅 TOMI_4_Ada 包TCP_Connect中 Monitor_Connections 过程的开始(第 397-416 行)。Monitor_Connections 从任务 Connection_Monitoring 中调用(第 469-495 行)。

于 2012-08-20T12:34:51.197 回答