我当前的设计看起来像这样
task body Agent_Task is
begin
loop
select
accept Request_A do
end Request_A;
or
accept Request_B do
end Request_B;
or
...
else
Do_Other_Stuff;
end select;
end loop;
exception
when Exception_Id : others => Show_Exception (Exception_Id);
end Agent_Task;
Run Code Online (Sandbox Code Playgroud)
但是,当频繁调用代理中的条目(例如Request_A)时,它将变得无响应。有没有更好的结构让代理永远不会被阻塞?比如中断?
最耗时的部分在Do_Other_Stuff中,我希望服务器做的事情大致是:
loop
Do_Other_Stuff;
if interrupted, handle other requests.
end loop;
Run Code Online (Sandbox Code Playgroud)
这是一个学校协会,我无法修改测试程序来重试向代理发送的失败请求。当测试运行时,多个代理将同时相互通信。
请注意,您的代码中有一个虚假end;代码,使其非法。
如果重要的是那些发出请求的人不会阻塞,您可以使用受保护的队列进行任务间通信:
loop
select
Request_Queue.Get (Item => Request);
Process (Request => Request);
else
Do_Other_Stuff;
end select;
end loop;
Run Code Online (Sandbox Code Playgroud)
请求在完成之前不会被处理Do_Other_Stuff,但是那些发出请求的人不会因为将请求放入队列而被阻止。
使用队列还允许您使用异步控制传输来为请求提供优先级Do_Other_Stuff:
loop
select
Request_Queue.Get (Item => Request);
Process (Request => Request);
then abort
Do_Other_Stuff;
end select;
end loop;
Run Code Online (Sandbox Code Playgroud)
Do_Other_Stuff然后需要可中止,并且能够在下次运行时从中断处继续。Do_Other_Stuff但如果能像霍尔斯蒂建议的那样转移到另一项任务中那就更好了。
最后,如果您无法移动Do_Other_Stuff到另一个任务,并且无法中止它,您可能需要将其分成更短的部分:
loop
Do_Some_Stuff;
Handle_Requests;
Do_Some_More_Stuff;
Handle_Requests;
..
end loop;
Run Code Online (Sandbox Code Playgroud)
同样,使用队列更容易,因为accept语句不能进入子程序。
将Do_Other_Stuff移至另一个任务,即将您的Agent_Task分成两个任务。
这有多困难取决于 Do_Other_Stuff 与 Request_A 和 Request_B 的操作之间有多少通信(数据流)。如果 Do_Other_Stuff 移至其自己的任务,则该任务必须通过集合点或受保护对象以某种方式与原始 Agent_Task 进行通信。如果 Do_Other_Stuff 是一个具有一些输入和一些输出的长计算,您可以向 Agent_Task 添加两个条目,一个用于向 Other_Stuff 任务提供输入,另一个用于接收来自 Other_Stuff 任务的输出。