处理长时间运行、阻塞功能



在一个项目中,我必须使用一个导入的C函数,该函数向服务器发送请求并接收响应。如果服务器不可访问,则可以向该函数提供超时参数,以指定阻止函数返回之前的最长时间。

不幸的是,这个超时并不总是可靠的,并且经常超过最大超时值。处理这类问题的最佳Ada方法是什么?

看完这一章后,我不确定我是否可以使用这种编程模式?导入的C函数不是线程安全的,因此一次只能有一个请求。一个完美的解决方案允许发送一个请求(带有有效响应或通常由导入的C函数返回的超时响应(,并且可以使用第二个函数来查询最后一个请求是否超时。在导入的C函数调用返回更多请求之前,应始终返回timout响应。

我不确定如果选择了延迟选项,条目(条目中的编程语句(Password_Server.SetProcess_Data.Output调用会发生什么?

如果入口调用排队或等待访问受保护对象(PO(,则在延迟到期时中止入口调用,执行延迟分支,并完成选择。如果延迟到期时入口调用已被接受(任务(或正在执行(PO(,则它将继续,直到完成或重新排队。如果完成,则执行入口分支并完成选择。如果通过中止重新排队,它的行为与最初一样。如果在不中止的情况下重新排队,则忽略延迟分支。(请注意,如果它在没有中止的情况下重新排队,那么以后仍然可以在有中止的情况下来重新排队,所以事情可能会更复杂。最好尽量避免这样的设计。(

IIUC正确地说,您一次只希望一个任务能够调用C操作。如果一个任务正在调用它,而另一个任务尝试调用它,则应告知第二个任务调用超时。如果C操作花费的时间超过超时时间,Ada应该中止该操作。

我能看到的中止对C的调用的唯一方法是使用异步控制传输。这是否真的会达到人们想要的效果,这是一个悬而未决的问题。

这让我想到了类似的东西

package Calling_C is
type Data is ...
procedure Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean);
end Calling_C;
package body Calling_C is
task Control is
entry Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean);
end Control;
task body Control is
begin
Forever : loop
select
accept Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean) do
select
delay Timeout;
Timed_Out := True;
then abort
-- Call the C operation
end select;
end Call_C;
or
terminate;
end select;
end loop Forever;
end Control;
procedure Call_C (Info : in Data; Timeout : in Duration; Timed_Out : out Boolean) is
begin
select
Control.Call_C (Info => Info, Timeout => Timeout, Timed_Out => Timed_Out);
else
Timed_Out := True;
end Select;
end Call_C;
end Calling_C;

第一个任务进入并调用C操作。后续任务不会立即被接受,并在Timed_Out设置为True的情况下返回。如果对C的调用没有及时返回,可能会中止。

我其实还不太了解阿达。在这里发布我的想法,这样专业人士就可以告诉我这是否是个坏主意。服务器看起来像这样:

task Server is
entry Request (in Input : Input_Type);
entry Response (out Output : Output_Type);
end Server;
task body Server is
Local_Input : Input_Type;
Local_Output : Output_Type;
begin
accept Request (Input : in Input_Type) do
Local_Input := Input;
end Request;
Local_Output := My_C_Code(Local_Input);
accept Response(Output : out Output_Type) do
Output := Local_Output;
end Response;
end Server;

如何使用:

Server.Request(Input);
select
Server.Response(Output);
-- got your response
or
delay Timeout;
-- response timeout
end select;

正如你可能已经意识到的那样,服务器会阻止响应,直到请求调用方(或其他任何人(决定调用它。我的最佳猜测是a(添加select ... or terminate,或者b(处理超时并返回等待响应、同步或异步。

最新更新