Ada 将有限的私有类型传递给任务
Ada pass limited private type to task
我有一种情况,我想给一个任务一个有限的私有类型,这样它就可以调用它的各种函数(特别是它是来自 GNAT.Serial_Communications
的串行端口)。但是,我似乎无法弄清楚如何让它工作。
我试过直接传递它,直到我必须使用该类型时,它一直有效,此时我无法将它复制到保存的变量中:
task body MyTask is
MyT : LPType;
begin
accept MyEntry (t : LPType) do
MyT := t; -- not valid, LPType is limited private
end MyEntry;
-- Later I do something using MyT
end MyTask;
因为这不起作用,我尝试传递对有限私有类型的访问,不幸的是,由于访问的局部性,这仍然不起作用:
procedure MyProcedure is
MyT : aliased LPType;
Task : MyTask;
begin
Initialize (MyT);
Task.MyEntry (MyT'Access);
end MyProcedure;
从技术上讲,我是通过使用 Unrestricted_Access
来编译它的,但这感觉就像是 hack,根据我的经验,当你使用 hack 绕过 Ada 中的编译器时,编译器有充分的理由强迫你这样做这样做,你就犯了一个错误。
所以我的问题是:是否可以通过条目将有限的私有类型传递给任务,或者这只是一个坏主意吗?
在 Ada 中,limited
关键字表示该类型没有与之关联的赋值。这与大多数主流语言完全相反,但考虑像 [physical-]clock- 或 RNG 类型的东西:复制这些是没有意义的,因此以这种方式建模是有意义的。
但是,task
构造不能保证与调用其条目的线程位于同一内存中-space。 -- 所以我们在这里有点矛盾:limited
禁止复制而 entry
需要某种形式的复制。
有多种方法可以解决此问题,但考虑到您提供的代码片段,解决方案是使 task
成为 limited
类型的组件。
Package Example is
Type LP is limited private;
Function Create return LP;
Function Create( Value : Integer ) return LP;
Procedure Print( Object : LP );
Private
Task Type Printer( Item : not null access LP ) is
Entry Print;
End Printer;
Type LP is limited record
Value : Integer := 100;
Task_Item : Printer(LP'Access);
end record;
end Example;
Package Body Example is
Function Create return LP is (others => <>);
Function Create( Value : Integer ) return LP is
(Value => Value, others => <>);
Procedure Print( Object : LP ) is
Begin
Object.Task_Item.Print;
end Print;
Task Body Printer is
Begin
accept Print do
Null;
end Print;
Ada.Text_IO.Put_Line( "Value:" & Integer'Image(Item.Value) );
End Printer;
end Example;
我有一种情况,我想给一个任务一个有限的私有类型,这样它就可以调用它的各种函数(特别是它是来自 GNAT.Serial_Communications
的串行端口)。但是,我似乎无法弄清楚如何让它工作。
我试过直接传递它,直到我必须使用该类型时,它一直有效,此时我无法将它复制到保存的变量中:
task body MyTask is
MyT : LPType;
begin
accept MyEntry (t : LPType) do
MyT := t; -- not valid, LPType is limited private
end MyEntry;
-- Later I do something using MyT
end MyTask;
因为这不起作用,我尝试传递对有限私有类型的访问,不幸的是,由于访问的局部性,这仍然不起作用:
procedure MyProcedure is
MyT : aliased LPType;
Task : MyTask;
begin
Initialize (MyT);
Task.MyEntry (MyT'Access);
end MyProcedure;
从技术上讲,我是通过使用 Unrestricted_Access
来编译它的,但这感觉就像是 hack,根据我的经验,当你使用 hack 绕过 Ada 中的编译器时,编译器有充分的理由强迫你这样做这样做,你就犯了一个错误。
所以我的问题是:是否可以通过条目将有限的私有类型传递给任务,或者这只是一个坏主意吗?
在 Ada 中,limited
关键字表示该类型没有与之关联的赋值。这与大多数主流语言完全相反,但考虑像 [physical-]clock- 或 RNG 类型的东西:复制这些是没有意义的,因此以这种方式建模是有意义的。
但是,task
构造不能保证与调用其条目的线程位于同一内存中-space。 -- 所以我们在这里有点矛盾:limited
禁止复制而 entry
需要某种形式的复制。
有多种方法可以解决此问题,但考虑到您提供的代码片段,解决方案是使 task
成为 limited
类型的组件。
Package Example is
Type LP is limited private;
Function Create return LP;
Function Create( Value : Integer ) return LP;
Procedure Print( Object : LP );
Private
Task Type Printer( Item : not null access LP ) is
Entry Print;
End Printer;
Type LP is limited record
Value : Integer := 100;
Task_Item : Printer(LP'Access);
end record;
end Example;
Package Body Example is
Function Create return LP is (others => <>);
Function Create( Value : Integer ) return LP is
(Value => Value, others => <>);
Procedure Print( Object : LP ) is
Begin
Object.Task_Item.Print;
end Print;
Task Body Printer is
Begin
accept Print do
Null;
end Print;
Ada.Text_IO.Put_Line( "Value:" & Integer'Image(Item.Value) );
End Printer;
end Example;