首页 > 解决方案 > 如何在 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;

这是一个学校协会,我无法修改测试程序以重试对代理的失败请求。当测试运行时,多个代理将同时相互交谈。

标签: ada

解决方案


请注意,您的代码中有一个虚假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语句不能进入子程序。


推荐阅读