ada - 如何在 Ada 中实现非阻塞服务器?
问题描述
我目前的设计看起来像这样
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;
但是当频繁调用代理中的条目时(例如 Request_A),它将变得无响应。有没有更好的结构让代理永远不会被阻塞?像中断?
最耗时的部分是在Do_Other_Stuff中,我希望服务器做的大致是:
loop
Do_Other_Stuff;
if interrupted, handle other requests.
end loop;
这是一个学校协会,我无法修改测试程序以重试对代理的失败请求。当测试运行时,多个代理将同时相互交谈。
解决方案
请注意,您的代码中有一个虚假end;
代码,使其非法。
如果重要的是那些发出请求的人不会阻塞,您可以使用受保护的队列进行任务间通信:
loop
select
Request_Queue.Get (Item => Request);
Process (Request => Request);
else
Do_Other_Stuff;
end select;
end loop;
请求在完成之前不会被处理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;
Do_Other_Stuff
然后需要可中止,并且能够在下次运行时从中断的地方继续。但如果Do_Other_Stuff
能按照 Holsti 的建议转移到另一项任务中,那就更好了。
最后,如果你不能移动Do_Other_Stuff
到另一个任务,并且你不能中止它,你可能需要把它分成更短的部分:
loop
Do_Some_Stuff;
Handle_Requests;
Do_Some_More_Stuff;
Handle_Requests;
..
end loop;
同样,使用队列更容易,因为accept
语句不能进入子程序。