最初にコードでこの質問を説明しましょう:
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チュートリアル、ウィキブックスでいくつかの例を見てきましたが、実際には何も適切ではないようでした。
エイダでのそのような(私が信じるかなり一般的な)問題のベストプラクティスは何ですか?
そして答えは...
Marc Cの回答に基づくソリューションの例:https ://gist.github.com/3413017