让我先用代码说明这个问题:
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中这种(相当常见的我相信)问题的最佳做法是什么?
答案是......
的解决方案示例答案 0 :(得分:2)
您需要else版本:
loop
-- blocking read from socket
-- process the data received
select
accept Stop;
exit;
else
null;
end select;
end loop;
答案 1 :(得分:2)
我通常设置它的方法首先是使用AdaCore的GNAT.Sockets包,而不是直接编程套接字。由于我将使用(套接字)select()函数(包装为Check_Selector)在套接字上有数据时通知,GNAT.Sockets提供了一个可以从其他地方调用的Abort_Selector()过程。在Check_Selector()上阻止任务时,我只是等待数据到达(状态=已完成)或标志它是时候退出(状态=已中止)。
请参阅TOMI_4_Ada包TCP_Connect中Monitor_Connections过程的开始(第397-416行)。从任务Connection_Monitoring(第469-495行)调用Monitor_Connections。